即使状态发生变化,反应也不会对组件进行更改

时间:2017-02-27 13:21:19

标签: reactjs

我按照反应主页here中的教程进行操作。我想修改x-o游戏代码以在游戏中前进和后退。我包括下面的代码。

历史记录记录在历史列表中,pos是列表中当前选择的索引。

如您所见,我有三个按钮:重置,向上,向下。按Reset时我重置状态。当你按下时,我增加了pos。当你按下时,我减少了pos。我也在展示pos来检查。

问题是pos正在更新,但组件没有重新渲染。为了便于使用,我包括了heroku here

我在这里缺少什么?

addElements :: [Int] -> [Int] -> [Int]
addElements [] [] = []
addElements x:xs [] = x:xs
addElements [] y:ys = y:ys
addElements x:xs y:ys = [x+y] ++ addElements xs ys

编辑:

在handleClick()中更改了

    import React, { Component } from 'react';
import './App.css';


function Square(props){
    return (
        <div className="square" onClick={() => props.onClick()}>
            {props.value}
        </div>
    );
}

function calculateWinner(squares){
    const winners = [
        [0, 1, 2],
        [3, 4, 5],
        [6, 7, 8],
        [0, 4, 8],
        [2, 4, 6],
        [0, 3, 6],
        [1, 4, 7],
        [2, 5, 8]
    ];
    for(let i = 0; i < winners.length; i++){
        const [a, b, c] = winners[i];
        if(squares[a] && squares[b] === squares[a] && squares[c] === squares[a]){
            return squares[a];
        }
    }
    return null;
}

class Board extends Component{
    constructor() {
        super();
        this.state = {
            history: [Array(9).fill(null)],
            pos : 0,
            xIsNext: true
        }
    }

    handleClick(i){
        const current = this.state.history[this.state.pos];
        if (current[i] || calculateWinner(current)) {

        } else {
            const history = this.state.history.slice();
            const squares = history[this.state.pos].slice();
            squares[i] = this.state.xIsNext ? "X" : "O";
            history[this.state.pos + 1] = squares;
            this.setState({
                history: history,
                pos: this.state.pos + 1,
                xIsNext: !this.state.xIsNext
            });
        }
    }

    clickReset(){
        this.setState(
            {
                history: [Array(9).fill(null)],
                pos : 0,
                xIsNext: true
            }
        );
    }
    clickUp(){
        let pos = this.state.pos;
        if(pos < this.state.history.length) {
            pos += 1;
            this.setState(
                {
                    pos: pos,
                    xIsNext: !this.state.xIsNext
                }
            );
        }
    }
    clickDown(){
        let pos = this.state.pos;
        if(pos > 0) {
            pos -= 1;
            this.setState(
                {
                    pos: pos,
                    xIsNext: !this.state.xIsNext
                }
            );
        }
    }
    renderSquare(i){
        let current = this.state.history[this.state.pos];
        return (
            <Square value={current[i]} onClick={() => this.handleClick(i)}/>
        )
    }

    render() {
        let status ;
        const pos = this.state.pos;
        const current = this.state.history[pos];
        const winnerCal = calculateWinner(current);
        if (winnerCal){
            status = "Winner : " + winnerCal;
        } else {
            status = "Next Play : " + (this.state.xIsNext ? "X" : "O");
        }
        return (
            <div className="col">

                <div className="row justify-content-center">
                    <div className="board-row">
                        {this.renderSquare(0)}
                        {this.renderSquare(1)}
                        {this.renderSquare(2)}
                    </div>
                    <div className="w-100"></div>
                    <div className="board-row">
                        {this.renderSquare(3)}
                        {this.renderSquare(4)}
                        {this.renderSquare(5)}
                    </div>
                    <div className="w-100"></div>
                    <div className="board-row">
                        {this.renderSquare(6)}
                        {this.renderSquare(7)}
                        {this.renderSquare(8)}
                    </div>
                </div>
                <div className="row justify-content-center">
                    {status} pos: {pos}
                </div>
                <div className="row-fluid">
                    <button type="button" className="col-md-4 btn btn-warning" onClick={() => this.clickReset()}>Reset</button>
                    <button type="button" className="col-md-4 btn btn-danger" onClick={() => this.clickUp()}>up</button>
                    <button type="button" className="col-md-4 btn btn-info" onClick={() => this.clickDown()}>down</button>
                </div>
            </div>
        )
    }
}
class App extends Component {

    renderHeader(){
        return (
            <div className="row justify-content-center">
                <div className="col"></div>
                <div className="col">
                    <h3 className="row justify-content-center"> Lets build a xo game </h3>
                </div>
                <div className="col"></div>
            </div>
        )
    }

    renderBoard(){
        return (
            <div className="row">
                <div className="col"></div>
                <Board className="col"/>
                <div className="col"></div>
            </div>
        )
    }

    render() {
        return (
            <div className="container">
                {this.renderHeader()}
                {this.renderBoard()}
            </div>
        );
    }
}

export default App;

const squares = history[this.state.pos]
..
history[history.length] = squares;

1 个答案:

答案 0 :(得分:1)

您的方法很可能运作良好。问题是你的历史被覆盖了

const squares = history[this.state.pos];
squares[i] = this.state.xIsNext ? "X" : "O";
history[history.length] = squares;

导致历史[history.length]引用与历史[history.length - 1]相同的对象,依此类推至历史[0]

尝试使用

const squares = history[this.state.pos].slice();