【问题标题】:React state = understanding how to read state after updatingReact state = 了解更新后如何读取状态
【发布时间】:2021-07-17 22:57:56
【问题描述】:

我非常精通 JavaScript,但正在学习 React。我正在尝试做井字游戏。当我获得胜利时,我希望 this.state.message 立即更新,this.state.done 立即更改为 true,并且 this.state.turn 不更改。目前我已经弄清楚了其中的一些,但没有弄清楚 this.state.turn 的变化。它说错误的玩家获胜。我知道 setState 是异步的,这就是为什么我无法一起更新这些东西,我通过回调修复了其中一些,但我正在尝试找到更好的方法并更好地理解所有内容。

class Board extends Component {
    constructor(props) {
        super(props);
        this.state = {
            board: ['', '', '', '', '', '', '', '', ''],
            turn: 'O',
            message: 'O goes',
            done: false
        }
    }
    
    addItem(x) {
        if (this.state.done === true) {
            this.setState({message: this.state.turn + ' wins'});
            return;
        }
        let array = [...this.state.board];
        if (array[x] !== "") {
            return;
        }
        array[x] = this.state.turn;
        this.setState({board: array}, () => {
            this.checkWinners(0, 1, 2);
            this.checkWinners(3, 4, 5);
            this.checkWinners(6, 7, 8);
            this.checkWinners(0, 3, 6);
            this.checkWinners(1, 4, 7);
            this.checkWinners(2, 5, 8);
            this.checkWinners(0, 4, 8);
            this.checkWinners(2, 4, 6);
            if (this.state.done === false) {                                        
                this.setState({turn: (this.state.turn === "X") ? "O" : "X"});
                this.setState({message: (this.state.message === "X goes") ? "O goes" : "X goes"});
            }
        });
    }
    
    checkWinners(a, b, c) {
        if ((this.state.board[a] === "X"
            &&
            this.state.board[b] === "X"
            &&
            this.state.board[c] === "X")
            ||
            (this.state.board[a] === "O"
            &&
            this.state.board[b] === "O"
            &&
            this.state.board[c] === "O"
            )
            ) {
            this.setState({done: true}, () => {
                console.log('Winner');
                this.setState({message: this.state.turn + ' wins'});
            });

            }
    }
    
    render() {
        return (
            <>
            <h1>Tic-Tac-Toe</h1>
            <h2>{this.state.message}</h2>
            <div className="board">
            {this.state.board.map((item, index) => (
                <div className="boxes" key={index} onClick={() => this.addItem(index)}>{this.state.board[index]}</div>
            ))}
            </div>
            </>
        )
    }
}

【问题讨论】:

  • 更新后不要直接读取状态。设置状态是异步的。你不能指望它马上是最新的
  • @evolutionxbox 感谢您的回答。也许我应该问一个不同的问题。我知道设置状态是异步的,但我想知道如何在同一个 onClick 中更改所有这些内容,因为如果有人获胜,我希望游戏在他们采取行动后立即告诉他们。
  • 不要多次调用setState(),而是先收集更改,然后再调用一次。
  • @RoboRobok 谢谢。我仍然不明白的是,过牌赢家取决于董事会的状态,然后更新或不更新转牌的状态取决于过牌赢家。我不明白如何将这些放在一起。
  • 我想说的是,您基于该行的 checkWinners() 方法的设计相当糟糕。它应该自己检查所有可能性,并且仅在必要时继续。一般来说,通常在 React 中,中间有这个状态是不错的,因为它只影响 UI,并且有一个渲染周期作为中间状态通常很好。

标签: javascript reactjs asynchronous setstate


【解决方案1】:

您可以尝试以下代码,只是更改了checkWinners 函数的逻辑并注释掉了this.setState({ message: this.state.turn + " wins" }); 行。 [注意:更改了一些 css 以在本地测试]

   constructor(props) {
        super(props);
        this.state = {
            board: ["", "", "", "", "", "", "", "", ""],
            turn: "O",
            message: "O goes",
            done: false,
        };
    }

    addItem(x) {
        if (this.state.done === true) {

            // this.setState({ message: this.state.turn + " wins" });
            return;
        }
        let array = [...this.state.board];
        if (array[x] !== "") {
            return;
        }
        array[x] = this.state.turn;
        this.setState({ board: array }, () => {
            this.checkWinners(0, 1, 2);
            this.checkWinners(3, 4, 5);
            this.checkWinners(6, 7, 8);
            this.checkWinners(0, 3, 6);
            this.checkWinners(1, 4, 7);
            this.checkWinners(2, 5, 8);
            this.checkWinners(0, 4, 8);
            this.checkWinners(2, 4, 6);
            if (this.state.done === false) {
                this.setState({ turn: this.state.turn === "X" ? "O" : "X" });
                this.setState({
                    message:
                        this.state.message === "X goes" ? "O goes" : "X goes",
                });
            }
        });
    }

    checkWinners(a, b, c) {
        if( this.state.board[a] === "X" &&
            this.state.board[b] === "X" &&
            this.state.board[c] === "X"){
            this.setState({ done: true }, () => {
                console.log("Winner");
                this.setState({ message: "X wins" });
            });
        }else if(this.state.board[a] === "O" &&
            this.state.board[b] === "O" &&
            this.state.board[c] === "O"){
            this.setState({ done: true }, () => {
                console.log("Winner");
                this.setState({ message: "O wins" });
            });
        }
    }

    render() {
        return (
            <>
                <h1>Tic-Tac-Toe</h1>
                <h2>{this.state.message}</h2>
                <div className="board container" style={{height:"500px",width:"500px"}}>
                    <div className={"row"} style={{minHeight:"80%"}}>
                        {this.state.board.map((item, index) => (
                            <div
                                className="col-3 bg-secondary m-1"
                                key={index}
                                onClick={() => this.addItem(index)}
                            >
                                {this.state.board[index]}
                            </div>
                        ))}
                    </div>
                </div>
            </>
        );
    }

【讨论】:

    猜你喜欢
    • 2018-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-17
    • 1970-01-01
    • 2017-03-22
    • 2017-01-19
    • 1970-01-01
    相关资源
    最近更新 更多