React:对象数组的setState更改每个项目

时间:2018-03-14 15:12:50

标签: reactjs setstate

我正在使用React构建记忆游戏。我有一系列卡片,每张卡片可以匹配" (用户刚刚点击它)或"匹配" (用户已找到两张卡,现在它们已完全显示)。我的问题是,当我尝试使用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')
);

3 个答案:

答案 0 :(得分:1)

您遇到的问题是您没有为每张卡创建4个独立对象。您正在创建一个对象,该对象在阵列中出现四次。这意味着更改任何索引会影响所有索引。

Array.fill的工作原理。

要创建四个独立状态,您需要以下内容:

const cards = [];
for(var i = 0; i < 4; i++) {
  cards.push({
    matched: false,
    matching: false
  ));
}

答案 1 :(得分:0)

您可以为每个o.f组件添加shouldComponentUpdate,以防止不必要的重新渲染:

Card

或者你可以专门针对一个道具:

shouldComponentUpdate(prevProps, prevState) {
    return prevProps !== this.props
}

答案 2 :(得分:-1)

这正是预期的结果:您在状态中设置了一个新的对象数组,因此为每个对象再次调用了渲染