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>
);
}
}