【发布时间】:2018-02-23 16:15:54
【问题描述】:
我在这里阅读了 react 文档和示例: When to use React setState callback
我正在尝试使用回调来让setState() 立即更新。但是我的背景颜色,或者squaresColor[i] 仍然没有更新。
console.log(squaresColor[i]) 正在输出 undefined: green。绿色是正确的,但关键是undefined。
我尝试了..setState(squaresColor: squaresColor),但是按下回车键后,背景仍然没有改变。无论出于何种原因,我在不同的方法中使用相同的setState,handleClick()。这是异步调用的,并且工作正常。
那么为什么handleKeyPress 中的背景颜色没有更新?我不应该使用状态来进行此更新吗?
我的代码:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
/*stop clicking ability after clicking a problem (prevent default) and enable it when submit is done.*/
/* let btnStyle = {
backgroundColor: 'green'
} */
/*we also changed onClick={() => props.onClick()} to just onClick={props.onClick},
as passing the function down is enough for our example. Note that onClick={props.onClick()}
would not work because it would call props.onClick immediately instead of passing it down.*/
class Square extends React.Component
{
render()
{
return (
<button className="square" onClick = {this.props.onClick} style = {{backgroundColor: this.props.backgroundColor}}>
{this.props.value}
{this.props.txt}
</button>
);
}
}
class Board extends React.Component
{
constructor(props)
{
super(props);
this.state =
{
squares: Array(25).fill(null),
xIsNext: true,
squaresColor: Array(25).fill('null'),
num1: generateRandomNumber(),
num2: generateRandomNumber(),
ans: function(a,b){return(a * b);},
sqTxt: Array(25).fill(null),
next: true
};
//this.handleKeyPress = this.handleKeyPress.bind(this);
}
handleClick(i)
{
const squares = this.state.squares.slice(); // makes a mutable copy of the array
const squaresColor = this.state.squaresColor.slice(); // makes a mutable copy of the array
const sqTxt = this.state.sqTxt.slice(); // makes a mutable copy of the array
if (!(this.state.next) || squares[i])
{
return;
}
squaresColor[i] = 'blue';
sqTxt[i] = <input onKeyPress = {(e,i) => this.handleKeyPress(e, i)} className = 'answer-input' type = 'text' name = 'answer' />;
this.setState({
squares: squares,
squaresColor: squaresColor,
sqTxt: sqTxt,
next: false
});
console.log(this.state.squaresColor[i]);
squares[i] = this.state.num1 + ' X ' + this.state.num2;
return this.state.next;
}
/*When an event is invoked, it will be passed an event object as it's first argument. You can name evt whatever you like. Common names are e evt and event.*/
handleKeyPress(e, i)
{
const userAnswer = parseInt(e.target.value, 10);
const num1 = this.state.num1;
const num2 = this.state.num2;
const correctAnswer = num1 * num2;
const squaresColor = this.state.squaresColor.slice(); // makes a mutable copy of the array
if(e.key === 'Enter')
{
squaresColor[i] = 'green';
if(userAnswer === correctAnswer)
{
this.setState({
/* squaresColor: */ squaresColor,
next: true,
}/* , function()
{
console.log(this.state.squaresColor);
this.setState(squaresColor: squaresColor);
} */);
//create new numbers for next problem
this.setState({num1: generateRandomNumber(), num2: generateRandomNumber()});
}
else
{
console.log('incorrect');
}
}
}
renderSquare(i)
{
return (
<Square
value={this.state.squares[i]}
onClick = {() => this.handleClick(i)}
backgroundColor = {this.state.squaresColor[i]}
txt = {this.state.sqTxt[i]}
/>
);
}
render()
{
return (
<div className = 'all-rows'>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
{this.renderSquare(3)}
{this.renderSquare(4)}
</div>
<div className="board-row">
{this.renderSquare(5)}
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
{this.renderSquare(9)}
</div>
<div className="board-row">
{this.renderSquare(10)}
{this.renderSquare(11)}
{this.renderSquare(12)}
{this.renderSquare(13)}
{this.renderSquare(14)}
</div>
<div className="board-row">
{this.renderSquare(15)}
{this.renderSquare(16)}
{this.renderSquare(17)}
{this.renderSquare(18)}
{this.renderSquare(19)}
</div>
<div className="board-row">
{this.renderSquare(20)}
{this.renderSquare(21)}
{this.renderSquare(22)}
{this.renderSquare(23)}
{this.renderSquare(24)}
</div>
</div>
);
}
}
class Game extends React.Component
{
render() {
return (
<div className="game">
<div className="gxame-board">
<Board />
</div>
<div className="game-info">
</div>
</div>
);
}
}
ReactDOM.render(
<Game />,
document.getElementById('root')
);
function generateRandomNumber()
{
return Math.floor(Math.random() * 10);
}
【问题讨论】:
-
为什么在 setState 回调中调用 setState ?
-
你可以通过
this.setState({squaresColor, next: true, num1: generateRandomNumber(), num2: generateRandomNumber()});简化你的状态更新 -
你能展示你是如何设置你的背景颜色的吗?哪个日志针对哪个
console语句。很难理解你的问题。 -
@Panther 抱歉,这是我的整个 js 文件。我已经编辑了我的原始帖子以包含整个文件。谢谢。
-
记得在你的构造函数中为你的事件处理程序重新绑定这个引用。
this.handleKeyPress = this.handleKeyPress.bind(this); this.handleClick = this.handleClick.bind(this);