#javascript #reactjs
Вопрос:
В настоящее время я изучаю реакцию и пытаюсь закодировать программируемую сетку, в которой поля меняют цвет при нажатии.
К сожалению, моя кнопка «Обновить сетку» работает не так, как предполагалось. Даже при нажатии на кнопки, которые были нажаты ранее, остаются активированными (т. е. их цвет оранжевый). Когда я сбрасываю состояние своей сетки при вызове setGrid()
, я не уверен, где я ошибаюсь.
Мы очень ценим вашу помощь. Поскольку я совершенно новичок в самой реакции, некоторые рекомендации о лучших практиках и т. Д. было бы также очень полезно!
Заранее спасибо.
Код:
import ReactDOM from 'react-dom';
import './index.css';
class Box extends React.Component {
constructor() {
super();
this.state = {
color: 'white',
activated: false
}
}
initiate() {
this.setState({color: 'white', activated:false})
}
componentDidMount() {
this.initiate()
}
click() {
if(!this.state.activated) {
this.setState({color: 'orange', activated: true})
}
else {
this.setState({color: 'white', activated: false})
}
}
render() {
return <div className="box" style={{ backgroundColor: this.state.color }} onClick={() => this.click()}/>
}
}
class Grid extends React.Component {
constructor() {
super();
this.state = {grid: []}
}
componentDidMount() {
this.setGrid()
}
setGrid() {
let grid = [];
for (let row = 0; row < 20; row ) {
for (let col = 0; col < 20; col ) {
grid.push(<Box />)
}
}
this.setState({grid: grid})
}
render() {
return (
<>
<div className="grid">{this.state.grid}</div>
<button onClick={() => this.setGrid()}>Refresh Grid</button>
</>
)
}
}
ReactDOM.render(
<Grid />,
document.getElementById('root')
);
Ответ №1:
Вы не назначаете ключ React элементам/компонентам, отображаемым в массиве, поэтому используется их относительный индекс, и, поскольку это не меняется от отрисовки к отрисовке, React отменяет повторный просмотр.
- Вы можете назначить уникальные ключи каждому
Box
компоненту, когда они будут созданы вgrid
состоянии. Вот пример использования генератора GUID отuuid
.import { v4 as uuidV4 } from 'uuid'; ... setGrid() { let grid = []; for (let row = 0; row < 5; row ) { for (let col = 0; col < 5; col ) { grid.push(<Box key={uuidV4()} />); // <-- add key } } this.setState({ grid: grid }); }
- Вы можете использовать одну клавишу для
div
рендерингаgrid
. Сбросьте это значение при настройке/сбросе сетки.import { v4 as uuidV4 } from 'uuid'; ... class Grid extends React.Component { constructor() { super(); this.state = { grid: [], key: uuidV4() }; } componentDidMount() { this.setGrid(); } setGrid() { const grid = []; for (let row = 0; row < 5; row ) { for (let col = 0; col < 5; col ) { grid.push(<Box />); } } this.setState({ grid, key: uuidV4() // <-- set/reset key }); } render() { return ( <> <div key={this.state.key} // <-- add key className="grid" > {this.state.grid} </div> <button onClick={() => this.setGrid()}>Refresh Grid</button> </> ); } }
Ответ №2:
Очистите существующую сетку и установите новую сетку
setGrid() {
this.setState({ grid: [] }, () => {
let grid = [];
for (let row = 0; row < 20; row ) {
for (let col = 0; col < 20; col ) {
grid.push(<Box />);
}
}
this.setState({ grid: grid });
});
}