你如何在点击事件中改变 React 的状态?

How do you change the state in React on a click event?

React 新手并使用 Create React App 创建了一个简单的井字游戏,但 运行 遇到以下问题:

在下面的代码中,如果我将 console.log(this.state.board) 添加到 handleClick() 函数,board 数组会发生变化,但它都是 X。有什么想法吗?

这是我的 App.js:

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

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      PLAYER_ONE_SYMBOL: "X",
      PLAYER_TWO_SYMBOL: "O",
      currentTurn: "X",
      board: [
        "", "", "", "", "", "", "", "", ""
      ]
    }
  }

  handleClick(index) {
    var this_board = this.state.board;
    this_board[index] = this.state.currentTurn;
    this.setState = ({
      board: this.state.board,
      currentTurn: this.state.currentTurn === this.state.PLAYER_ONE_SYMBOL ? this.state.PLAYER_TWO_SYMBOL : this.state.PLAYER_ONE_SYMBOL
    })
  }

  render() {
    return (
      <div className="board">
        {this.state.board.map((cell, index) => {
          return <div onClick={() => this.handleClick(index)} className="square">{cell}</div>;
        })}
      </div>
    );
  }
}

我的App.css:

.board {
  display: flex;
  width: 600px;
  height: 600px;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
}

.square {
  display: flex;
  height: 200px;
  width: 200px;
  box-sizing: border-box;
  border: 5px solid black;
  font-size: 5em;
  justify-content: center;
  align-items: center;
}

.square:hover {
  cursor: pointer;
  background-color: #80cd92;
}

EDIT:意识到我犯了一个愚蠢的错误,将 this.setState 视为表达式而不是函数,并编写了错误的语法。这有效:

this.setState({
  board: this.state.board,
  currentTurn: this.state.currentTurn === this.state.PLAYER_ONE_SYMBOL ? this.state.PLAYER_TWO_SYMBOL : this.state.PLAYER_ONE_SYMBOL
})

您的代码几乎没有问题。

  1. 如果您不在 render 函数中使用它,则不应在状态中保留任何值。在您的情况下,您没有在 render 函数中使用 PLAYER_ONE_SYMBOLPLAYER_TWO_SYMBOLcurrentTurn。所以你可以将它们定义为文件中的普通变量或组件的实例变量class.

  2. setState 是一个函数。您可以通过将状态更改作为对象或函数传递来调用它,其中 return 将状态更改作为对象传递。在 official documentation.

  3. 中阅读更多相关信息
  4. 你不应该改变之前的状态。您应该始终基于先前的状态创建新的对象状态而不改变它。

因此,您可以将您的 App 组件代码更改为如下内容以使其正常工作。

import React, { Component } from "react";
import { render } from "react-dom";
import "./App.css";

const PLAYER_ONE_SYMBOL = "X";
const PLAYER_TWO_SYMBOL = "O";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      board: ["", "", "", "", "", "", "", "", ""]
    };
    this.currentTurn = PLAYER_ONE_SYMBOL;
  }

  handleClick(index) {
    this.setState({
      board: this.state.board.map(
        (val, boardIndex) => (boardIndex === index ? this.currentTurn : val)
      )
    });

    this.currentTurn =
      this.currentTurn === PLAYER_ONE_SYMBOL
        ? PLAYER_TWO_SYMBOL
        : PLAYER_ONE_SYMBOL;
  }

  render() {
    return (
      <div className="board">
        {this.state.board.map((cell, index) => {
          return (
            <div onClick={() => this.handleClick(index)} className="square">
              {cell}
            </div>
          );
        })}
      </div>
    );
  }
}

请注意我是如何使用 setState 函数更改状态但没有改变状态的。 map 函数总是 return 一个没有 modifying/mutating 原始数组的新数组。