React-создание вложенных компонентов с циклами

у меня есть небольшая проблема с 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>

Я хочу уточнить, что я уверен, что остальная часть кода, с которой взаимодействует этот компонент (плата), не имеет проблем.

Я новичок в react, и если кто-то может мне помочь, я буду очень благодарен. Извините за мой бедный английский

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 ячейками, и ячейки являются одними и теми же объектами. Не понимаю почему. (Я понимаю, что это те же объекты, потому что я назначаю функцию дескриптора onClick, когда я создаю их так:

<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) стажера.

6 ответов


чтобы отобразить список элементов внутри 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 опора, как указал здесь.

кроме того, если вы хотите просто напечатать значение строки в своей функции рендеринга, вы должны заменить:

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

С:

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

или, все же, заменить forEach и push С map:

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

редактировать я создал скрипку с доской 9x9, используя ваш код в качестве базы:https://jsfiddle.net/mrlew/cLbyyL27/ (вы можете нажать на ячейку, чтобы выбрать ее)


Я вижу, что Вы тоже делаете учебник JS React! Вот что я сделал, но я работаю над этим, потому что должен быть хороший способ дать каждый из этих отдельных ключей.

я столкнулся с той же проблемой, с которой вы столкнулись, где X были нарисованы на 3 квадрата, и причина этого заключается в том, что, когда вы визуализировали квадраты, некоторые из "я" были дублированы. Таким образом, было несколько квадратов с "i" 2, например (по крайней мере, это было в моем выпуске).

Итак, каждый квадрат имеет индекс правильно? [0,1,2,3,4,5,6,7,8].

Сначала нам нужно найти, как они связаны таким образом, чтобы мы могли отображать их в строки! Итак, в вашем примере у вас есть index1 и index2, которые, я полагаю, будут ссылаться на координаты x и y квадрата на доске. Переписывая массив выше, мы приходим к: [{0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {2,1}, {0,2}, {1,2}, {2,2}] использование формата {x,y}. Как мы можем использовать эти значения (которые мы получим из вашего index1 и index2, чтобы получить исходный массив значений, который мы начали с [0,1,2,3,4,5,6,7,8]?

то, что я сделал, было 3 * x + y (или в цикле, 3 * i + j). Таким образом, каждый квадрат имеет уникальное значение "i", связанное с ним.

после того, как я настроил свои петли, я использовал этой 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;
}

тогда моя функция рендеринга на плате выглядит так:

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

вот лучшее, что я мог придумать после прочтения ответов здесь и в петля внутри 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. Я также делать вызовы в новые Реагировать Уроке. =p


вы нажимаете функции на board массив. Если вы хотите отобразить их, вы должны вызвать эти функции, такие как

{board[0]()}

Я подготовил пример, который охватывает вашу проблему:http://jsbin.com/hofohiy/edit?js, выход


Я также работаю над учебником 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, чтобы установить ключ для квадратного компонента в качестве второго аргумента.

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

живая демонстрация на 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>
    );  
  }
}