你如何在点击事件中改变 React 的状态?
How do you change the state in React on a click event?
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;
}
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
})
您的代码几乎没有问题。
如果您不在 render
函数中使用它,则不应在状态中保留任何值。在您的情况下,您没有在 render
函数中使用 PLAYER_ONE_SYMBOL
、PLAYER_TWO_SYMBOL
和 currentTurn
。所以你可以将它们定义为文件中的普通变量或组件的实例变量class.
setState
是一个函数。您可以通过将状态更改作为对象或函数传递来调用它,其中 return 将状态更改作为对象传递。在 official documentation.
中阅读更多相关信息
你不应该改变之前的状态。您应该始终基于先前的状态创建新的对象状态而不改变它。
因此,您可以将您的 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 原始数组的新数组。
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;
}
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
})
您的代码几乎没有问题。
如果您不在
render
函数中使用它,则不应在状态中保留任何值。在您的情况下,您没有在render
函数中使用PLAYER_ONE_SYMBOL
、PLAYER_TWO_SYMBOL
和currentTurn
。所以你可以将它们定义为文件中的普通变量或组件的实例变量class.setState
是一个函数。您可以通过将状态更改作为对象或函数传递来调用它,其中 return 将状态更改作为对象传递。在 official documentation. 中阅读更多相关信息
你不应该改变之前的状态。您应该始终基于先前的状态创建新的对象状态而不改变它。
因此,您可以将您的 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 原始数组的新数组。