React:对象数组的setState更改每个项目
React: setState of array of object changes every item
我正在使用 React 构建一个记忆游戏。我有一组卡片,其中每张卡片可以是 "matching"(用户刚刚点击它)或 "matched"(用户已经找到了两张卡片,它们现在已完全显示)。我的问题是,当我尝试使用 setState
设置匹配状态时,每张卡片的状态都会发生变化,而不仅仅是被点击的卡片。这是我拥有的:
import React from 'react';
import ReactDOM from 'react-dom';
import Card from './card';
import './index.css';
class Game extends React.Component {
constructor() {
super();
this.state = {
cards: Array(4).fill(
{
matching: false,
matched: false,
}
),
currentlyMatching: false,
}
}
handleCardClick(index, type) {
let currentCardsState = this.state.cards.slice();
currentCardsState[index].matching = true;
this.setState({cards: currentCardsState});
}
renderCard(index, type) {
return <Card value={type}
matching={this.state.cards[index].matching}
matched={this.state.cards[index].matched} // this line is the issue
onClick={() => this.handleCardClick(index, type)}
/>;
};
render() {
return <div id="game">
{this.renderCard(0,"red")}
{this.renderCard(1, "green")}
{this.renderCard(2, "red")}
{this.renderCard(3, "green")}
</div>;
};
}
ReactDOM.render(
<Game />,
document.getElementById('root')
);
这正是预期的结果:您在状态中设置了一个新的对象数组,因此会为每个对象再次调用渲染
您遇到的问题是您没有为每张卡片创建 4 个独立的对象。您正在创建 one 对象,该对象在数组中出现了四次。这意味着更改任何索引都会影响所有索引。
这就是 Array.fill
的工作方式。
要创建四个独立的状态,你需要这样的东西:
const cards = [];
for(var i = 0; i < 4; i++) {
cards.push({
matched: false,
matching: false
));
}
您可以在每个Card
组件中添加一个shouldComponentUpdate
以防止不必要的re-renders:
shouldComponentUpdate(prevProps, prevState) {
return prevProps !== this.props
}
或者您可以专门针对单个道具:
shouldComponentUpdate(prevProps, prevState) {
return prevProps.matched !== this.props.matched
}
我正在使用 React 构建一个记忆游戏。我有一组卡片,其中每张卡片可以是 "matching"(用户刚刚点击它)或 "matched"(用户已经找到了两张卡片,它们现在已完全显示)。我的问题是,当我尝试使用 setState
设置匹配状态时,每张卡片的状态都会发生变化,而不仅仅是被点击的卡片。这是我拥有的:
import React from 'react';
import ReactDOM from 'react-dom';
import Card from './card';
import './index.css';
class Game extends React.Component {
constructor() {
super();
this.state = {
cards: Array(4).fill(
{
matching: false,
matched: false,
}
),
currentlyMatching: false,
}
}
handleCardClick(index, type) {
let currentCardsState = this.state.cards.slice();
currentCardsState[index].matching = true;
this.setState({cards: currentCardsState});
}
renderCard(index, type) {
return <Card value={type}
matching={this.state.cards[index].matching}
matched={this.state.cards[index].matched} // this line is the issue
onClick={() => this.handleCardClick(index, type)}
/>;
};
render() {
return <div id="game">
{this.renderCard(0,"red")}
{this.renderCard(1, "green")}
{this.renderCard(2, "red")}
{this.renderCard(3, "green")}
</div>;
};
}
ReactDOM.render(
<Game />,
document.getElementById('root')
);
这正是预期的结果:您在状态中设置了一个新的对象数组,因此会为每个对象再次调用渲染
您遇到的问题是您没有为每张卡片创建 4 个独立的对象。您正在创建 one 对象,该对象在数组中出现了四次。这意味着更改任何索引都会影响所有索引。
这就是 Array.fill
的工作方式。
要创建四个独立的状态,你需要这样的东西:
const cards = [];
for(var i = 0; i < 4; i++) {
cards.push({
matched: false,
matching: false
));
}
您可以在每个Card
组件中添加一个shouldComponentUpdate
以防止不必要的re-renders:
shouldComponentUpdate(prevProps, prevState) {
return prevProps !== this.props
}
或者您可以专门针对单个道具:
shouldComponentUpdate(prevProps, prevState) {
return prevProps.matched !== this.props.matched
}