【问题标题】:How do you change the state in React on a click event?如何在点击事件上更改 React 中的状态?
【发布时间】:2017-12-29 00:10:59
【问题描述】:

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

  • 单击正方形后,“X”和“O”无法出现在 DOM 中
  • currentTurn 属性不会改变,它始终保持轮到 X 的状态

在下面的代码中,如果我将 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;
}

编辑:意识到我犯了一个愚蠢的错误,将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
})

【问题讨论】:

  • 发生这种行为是因为你正在变异this.state
  • this.setState 是一个函数。您需要传递一个对象而不是为其分配一个值。所以this.setState = ({ board: this.state.blah }) 应该是this.setState({ board: this.state.blah })
  • @norbertpy 这应该是一个答案而不是评论:)
  • @Kunukn,没有人有时间。
  • @norbertpy 谢谢刚刚意识到我在语法上犯了一个愚蠢的错误,为我的问题添加了一个编辑

标签: javascript reactjs jsx create-react-app


【解决方案1】:

您的代码几乎没有问题。

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

  2. setState 是一个函数。您可以通过将状态更改作为对象或将状态更改作为对象返回的函数来调用它。在official documentation 中阅读更多相关信息。

  3. 你不应该改变之前的状态。您应该始终根据之前的状态创建新的对象状态,而不是改变它。

因此,您可以将您的 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 函数总是返回一个新数组而不修改/改变原始数组。

【讨论】:

  • 感谢您在这里解释正确的 React 编码模式!
猜你喜欢
  • 1970-01-01
  • 2019-09-11
  • 1970-01-01
  • 1970-01-01
  • 2017-02-04
  • 1970-01-01
  • 2023-01-23
  • 2012-10-29
  • 2021-04-19
相关资源
最近更新 更多