#reactjs
#reactjs
Вопрос:
Я пытаюсь создать интерактивную сетку, которая при нажатии на ячейку увеличивает число только в этой конкретной ячейке. Вместо этого, когда я нажимаю на ячейку, увеличивается вся сетка, а не одна ячейка.
Я заставил React распечатать идентификатор кнопки, на которую был нажат. Он выводит только один (правильный) идентификатор. Я убедился, что передал функцию () => {}
вместо ее прямого вызова. Попытка удалить функцию arrow приводит к тому, что React жалуется на это this is undefined
.
Я знаю, что это может быть не лучшим способом (кого я обманываю, это самый ужасный способ) создания интерактивной сетки, но, пожалуйста, потерпите меня:
handleCellClick(id) {
let cells = this.state.cells.slice()
cells[id].level = cells[id].level 1 // Increment ONLY ONE CELL
console.log(cells[id]) // Logging to console only outputs one id, but it changes all of them?
this.setState({ cells: cells });
}
render() {
return (
<div className="board">
{
Array(resolution).fill(null).map((_, x) => { // Represents the rows
return (
<div className='cellRow' key={x}>
{
Array(resolution).fill(null).map((_, y) => { // Represents the columns
let id = (x * resolution) y
return (
<Cell
key={id}
onClick={() => { this.handleCellClick(id) }} // This is where it binds the click event
data={this.state.cells[id]}
/>
)
})
}
</div>
)
})
}
<p> {this.state.debug} </p>
</div>
)
}
Я ожидал, что при нажатии на одну ячейку, согласно приведенному выше коду, только эта ячейка должна увеличиваться, но вместо этого, при фактическом ее тестировании, она увеличивает все ячейки.
Подключение к React DevTools показывает, что каждая ячейка имеет свой элемент в массиве.
Вот функция конструктора.
class Board extends React.Component {
constructor(props) {
super(props);
this.handleCellClick = this.handleCellClick.bind(this);
this.state = {
cells: Array(resolution * resolution).fill({
level: 0,
owner: null,
}), // 5x5 for 25 in total
turn: 'red'
}
}
Комментарии:
1. Похоже, что при настройке вашего состояния вы присваиваете новое значение переменной всего массива, а не определенному элементу в массиве.
2. Почему вы пытаетесь использовать
this
функцию со стрелкой?3. Использование этого в функции со стрелкой будет ссылаться на правильную область здесь, потому что стрелки не создают контекст. Поэтому оно будет ссылаться на область видимости класса и правильно ссылаться на методы.
4. Я основал это на вводном руководстве по реагированию reactjs.org . Он использует
this
функции со стрелками, поэтому я подумал, что это нормально.5. @VladzislauUlasenka,
console.log(cells[0] === cells[1] ? "What?" : "Nope :(");
выводитWhat?
, что означает, что все элементы в массиве фактически ссылаются только на один объект… так вот в чем причина: (
Ответ №1:
Вы заполняете свой state.cells одним и тем же объектом, поэтому при изменении идентификатора одного объекта cell он запускает другие. Можете ли вы изменить свой конструктор, как показано ниже, и попробовать
class Board extends React.Component {
const cell = {
level: 0,
owner: null,
turn: 'red'
};
constructor(props) {
super(props);
this.handleCellClick = this.handleCellClick.bind(this);
this.state = {
cells: Array(resolution * resolution).fill(Object.create(cell))
}