React - 使用循环

时间:2017-01-15 23:04:18

标签: javascript loops reactjs inline jsx

我对React有点小问题。我无法使用for循环创建嵌套组件。我想要做的是创建一个表格的9个单元格,然后为每一行创建3行,每行包含3个单元格,之后将3行安装在一起,创建一个9x9的板。

假设我想得到类似的东西,但是使用循环

class Board extends React.Component {     
renderSquare(i) {
    return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />;
}

render(){    
    return(
        <div>
            <div className="board-row">
                {this.renderSquare(0)}
                {this.renderSquare(1)}
                {this.renderSquare(2)}
            </div>
            <div className="board-row">
                {this.renderSquare(3)}
                {this.renderSquare(4)}
                {this.renderSquare(5)}
            </div>
            <div className="board-row">
                {this.renderSquare(6)}
                {this.renderSquare(7)}
                {this.renderSquare(8)}
            </div>
        </div>
    );        
}

}

我搜索了其他问题几个小时,我认为我的代码几乎是正确的,但它没有呈现我想要的东西。我只得到一个白页。

这是我的代码:

class Board extends React.Component { 

renderSquare(i) {
    return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />;
}

createCells(i){
    if(i%3){return;}
    var index = this.fillN(Array(i)); //index=[0,1,2,3,4,5,6,7,8]
    var cells = [];
    index.forEach(function(i){
        cells.push(() => {
            return(
                <div>
                    {this.renderSquare(i)}
                </div>
            );
        });
    });
    return cells;
}

createRows(cells){
    var index = this.fillMod3(Array(3)); //index=[0,3,6]
    var rows = []
    index.forEach(function(i){
        rows.push(() => {
            return(
                <div>
                    {cells[i]}
                    {cells[i+1]}
                    {cells[i+2]}
                </div>
            );
        });
    });
    return rows;
}

render(){    
    var cells = this.createCells(9);
    var rows = this.createRows(cells);
    var board = [];
    var index = this.fillN(Array(1));

    index.forEach(function(row){
        board.push(() => {
            return(
                <div>{row}</div>
            );
        });
    })

    return(
        <div>
            {board[0]}
        </div>
    );        
}

我总是在屏幕上看到这样的东西:

<Board>
  <div> /*empty*/ </div>
</Board>

我想澄清一下,我确信该组件(Board)与之交互的其余代码没有问题。

我是新的反应,如果someoane可以帮助我,我会非常感激。 抱歉我的英语不好

EDIT1: 以下 marklew 示例我应该可以做这样的事情

    render(){   
    var index1 = this.fillN(Array(3)); //index1=[0,1,2]
    var index2 = this.fillN(Array(3)); //index2=[0,1,2]

    return(
        <div>
            {index1.map((e1,i1) => {
                return(
                    <div key={i1} className="board-row">
                        {index2.map((e2, i2) => {
                            return(
                                <p key={i2+10}>
                                    {this.renderSquare(i2)}
                                </p>
                            )
                        })}
                    </div>
                )    
            })}
        </div>
    );

}

但它没有做我想要的。我只得到一个包含9个单元格的列,单元格是相同的对象。我不明白为什么。 (我明白这些是相同的对象,因为我在创建它们时会分配一个句柄函数:

<Board 
     onClick={(i) => this.handleClick(i)} //handleClick just draws a X in the cell
     />

我将X同时淹没在3个牢房中

EDIT2: 我达成了解决方案:

render(){   
    var index1 = this.fillMod3(Array(3));        

    return(
        <div>
            {index1.map((e,i) => {
                return(
                    <div key={i} className="board-row">
                        {this.renderSquare(e)}
                        {this.renderSquare(e+1)}
                        {this.renderSquare(e+2)}
                    </div>
                )    
            })}
        </div>
    );

}

}

但不是我想要的。我想要实习生renderSquare(i)函数的另一个循环。

14 个答案:

答案 0 :(得分:12)

要在JSX中呈现元素列表,您可以执行以下操作:

render() {
    return <div>
        {
            [1,2,3].map ( (n) => {
                return this.renderSquare(n)
            })

        }
    </div>;
}   

将您的组件数组包装到JSX中的{}

为了澄清一下,这与以下逻辑相同:

return <div>
    {
        [
            <h1 key="1">Hello 1</h1>,
            <h1 key="2">Hello 2</h1>,
            <h1 key="3">Hello 3</h1>
        ]           
    }
</div>;

请注意,每次渲染组件数组时,都必须提供key道具,如指向here

此外,如果您只想在渲染功能中打印行值,则应替换:

index.forEach(function(row){
    board.push(() => {
        return(
            <div>{row}</div>
        );
    });
})

使用:

index.forEach( (row, index) => {
    board.push(<div key={index}>{row}</div>)
})

或者,用forEach替换pushmap

board = index.map( (row, index) => <div key={index}>{row}</div> )

编辑我使用您的代码作为基础创建了一个9x9板的小提琴:https://jsfiddle.net/mrlew/cLbyyL27/(您可以单击单元格来选择它)

答案 1 :(得分:5)

我也看到你正在做JS React教程!这就是我所做的,但我正在研究这个问题,因为必须有一个很好的方法来给出这些单独的密钥。

我遇到了你遇到的同样的问题,其中X被划分为3个方格,发生的原因是因为当你渲染方块时,一些“我的”被复制了。所以有多个Squares,其中“i”为2(至少在我的问题中就是这种情况)。

所以每个Square都有一个索引吗? [0,1,2,3,4,5,6,7,8]。

首先,我们需要找到这些相关的方式,以便我们可以将它们渲染成行!因此,在您的示例中,您有index1和index2,我假设它将引用Board中Square的x和y坐标。重新编写上面的数组我们来:[{0,0},{1,0},{2,0},{0,1},{1,1},{2,1},{0,使用{x,y}格式的2},{1,2},{2,2}]。我们如何使用这些值(我们可以从index1和index2获取这些值以获取我们从[0,1,2,3,5,5,7,8]开始的原始值数组?< / p>

我做的是3 * x + y(或循环,3 * i + j)。这样每个方块都有一个与之相关的唯一“i”值。

在我设置循环后,我使用this SO post来正确地返回我从单独的函数创建的元素(为了保持我的代码更清洁)。

这是我最终的结果,但我需要确保正确设置密钥,这实际上是我偶然发现这篇文章:

createSquares() {
  let rows = [];
  for(var i = 0; i < 3; i++){
    let squares = [];
    for(var j = 0; j < 3; j++){
      squares.push(this.renderSquare(3*i+j));
    }
    rows.push(<div className="board-row">{squares}</div>);
  }
  return rows;
}

然后我在Board中的渲染功能看起来像这样:

render() {
  return (
    <div>
      {this.createSquares()}
    </div>
  );
}

答案 2 :(得分:3)

在这里和Loop inside React JSX 中阅读答案后,我能想到的最好:

  render() {
    return (
      <div>
        {
          [...Array(3)].map((_, i) => (
            <div key={i} className="board-row">
              {
                [...Array(3)].map((_, j) => this.renderSquare(3 * i + j))
              }
            </div>
          ))
        }
      </div>
    );
  }

P.S。我也在新React Tutorial中面临挑战。 = P

答案 3 :(得分:1)

Live demo on codepen

render()函数中的嵌套循环  (注释中的解释:)

class Board extends React.Component {
  renderSquare(i) {
    return (
      <Square
        value={this.props.squares[i]}
        key={i}
        onClick={() => this.props.onClick(i)}
      />
    );
  }

  render() {
     var self = this;
    return (
      <div>
      // you can use: [...Array(3)] instead of [1,2,3]
        {[1, 2, 3].map(function(row, rowIdx) { // create rows 
          return (
            <div className="board-row" key={rowIdx}>
              {
              // you can use: [...Array(3)] instead of [1,2,3]
              [1, 2, 3].map((col, colIdx) => { // create columns
                return self.renderSquare((3 * rowIdx) + colIdx); // calculate square index
              })
              }
            </div>
          );
        })}
      </div>
    );  
  }
}

答案 4 :(得分:1)

这是我的解决方案。可能会有帮助。

IMDFError

答案 5 :(得分:0)

您正在将函数推送到board数组。如果你想渲染它们,你必须调用像

这样的函数
{board[0]()}

我准备了一个涵盖您问题的示例:http://jsbin.com/hofohiy/edit?js,output

答案 6 :(得分:0)

我也正在研究React教程。谢谢你的回复。我得到了这个解决方案:

render() {
    const rows = [];
    for(let i = 0; i<9; i=i+3) {
        const oneRow = [];
        for(let j = i; j < i+3; j++) {
            oneRow.push(this.renderSquare(j, j))
        }
        rows.push(<div className="board-row" key={i + 'someId'}>{oneRow}</div>)
    }
    return (
        <div>
            {rows}
        </div>
    );
}

我改变了renderSquare以设置Square组件的键,作为第二个参数。

renderSquare(i, key) {
    return (
        <Square
            value={this.props.squares[i]}
            onClick={() => this.props.onClick(i)}
            key={key}
        />
    );
}

答案 7 :(得分:0)

这应该可以解决您面临的问题。

即使对于内部renderSquare(i)函数,这也会添加另一个循环。 它可以满足您的要求,即在tic tac toe游戏中显示3列3单元格。

 render() {
    let count = 0;
    const index = [1, 2, 3];
    return (
      <div>
        {index.map((v, i) => {
          return (
            <div key={i} className="board-row">
              {index.map((v2, i2) => {
                return this.renderSquare(count++);
              })}
            </div>
          );
        })}
      </div>
    );
  }

答案 8 :(得分:0)

第一个解决方案:

import React from 'react';
import Square from './Square';

export default
class Board extends React.Component {
  render() {
    const board2 = [];

    for (let i = 0; i < 3; i++) {
      const s = [];
      for (let k = 0; k < 3; k++) {
        s[k] = <Square
          key     ={3*i+k}
          value   ={this.props.squares[3*i+k]}
          onClick ={()=>this.props.onClick(3*i+k)}
          />;
      }
      board2[i] = <div className="board-row" key={i}>{s}</div>;
    }
    ///////////////////////////////////////
    return (
      <div>{board2}</div>
    );
  }
}

第二种解决方法:

import React from 'react';
import Square from './Square';

export default
class Board extends React.Component {
  render() {    
    let board   =Array(3).fill(null);
    let square  =Array(3).fill(null);

    const x = board.map((b,bIndex)=>{
      return<div className="board-row" key={bIndex}>
        {
          square.map((s, sIndex)=>{
            return <Square
            key     ={3*bIndex+sIndex}
            value   ={this.props.squares[3*bIndex+sIndex]}
            onClick ={()=>this.props.onClick(3*bIndex+sIndex)}
            />;
          })
        }
      </div>;
    });
    ///////////////////////////////////////
    return (
      <div>{x}</div>
    );
  }
}

平方:

import React from 'react';

export default
function Square(props) {
  console.log('square render')
  return (
    <button className="square" onClick={props.onClick}>
      {props.value}
    </button>
  );
}

答案 9 :(得分:0)

我假设您正在看React教程示例。正如说明明确指出的那样,其想法是进行两个循环,而不仅仅是一个循环。

此示例中的第一个循环创建3行。第二个嵌套循环创建3个必要的列,并通过renderSquare函数为每个位置返回一个Square。您可能会注意到,我使用了两个循环的索引来正确地将相应的索引分配给正方形。

return (
    <div>
      {[0,1,2].map(i => {
        return (
          <div className="board-row">
            {[0,1,2].map(j => {
              return this.renderSquare(3*i + j)
            })}
          </div>
        );
      })}
    </div>
  );

答案 10 :(得分:0)

class Board extends React.Component {
  renderSquare(i) {
    return (<Square key={i} value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />);
  }

  render() {
    let board = [];
    for(let x = 0; x<3; x++){
      let lis =[];
      for(let y = 0; y<3; y++){
        lis.push(this.renderSquare(3*x + y));
      }
      board.push(<div key={x}>{lis}</div>)
    }
    return (
      <div>
        {board}
      </div>
    );
  }
}

答案 11 :(得分:0)

我的解决方法是:

class Board extends React.Component {

    //range is a Sequence generator function
    //Array.from(arrayLike[, mapFn [, thisArg]]).
    //arrayLike - An array-like or iterable object to convert to an array
    //mapFn - Map function to call on every element of the array
    //thisArg - Value to use as this when executing mapFn
    //range(0, 4, 1);  => [0, 1, 2, 3, 4] 

    range = (start, stop, step) => Array.from(
        { length: (stop - start)/step +1 }, 
        (_, i) => start + (i * step)
    );

    renderSquare(i) {
        return <Square 
            key={i}
            value={this.props.squares[i]} 
            onClickChange={() => this.props.onClickChange(i)} 
            />;
    }

    render() {
    let row = 3;
    let col = 3;
    return (
        <div>
            {
                //This generates an Array of [0, 3, 6] if row = 3 and col = 3
                // n is the element and i is the index of the element, i starts at 0
                this.range(0, row * col - 1, col).map( (n, i) => {
                    return (
                        <div key={i} className="board-row">
                            {
                                this.range(n, (i + 1) * col - 1, 1).map( (n, i) => {
                                return this.renderSquare(n)
                                })
                            }
                        </div>
                    )
                })
            }
        </div>
    );
}

答案 12 :(得分:0)

此代码段使用地图的方式类似于我们定义嵌套循环的方式。

const buildBoard = [0,1,2].map((row)=>{
      return (
        <div className='board-row' key={row}>
          {
            [0,1,2].map((col)=>{
              return (
                this.renderSquare(row*3+col)
              )
            })
          } 
        </div>
      )
    });

return (
      <div id ='Board Container'>
        {buildBoard}
      </div>

    );

答案 13 :(得分:0)

从教程中更改了董事会代码,以反映为

class Board extends React.Component {
  constructor(props) {
    super(props);
    this.rows = Array(3).fill(null);
  }
  
  renderSquare(i) {
    return (<Square
      key={i} 
      value={this.props.squares[i]}
      onClick={() => this.props.onClick(i)}
    />);
  }
  
  renderRow(row) {
    return (
      <div key={row} className="board-row">
        {this.rows.map((x, col) => this.renderSquare(3*row+col))}
      </div>
    );
  }

  render() {
    return (
      <div>
        {this.rows.map((x, rowIndex) => this.renderRow(rowIndex))}
      </div>
    );
  }
}
相关问题