我有一个draw()
函数,该函数更新了我的state.board
。
当我通过game()
的{{1}}函数调用它时,得到了预期的输出。
但是当我尝试直接调用它时,输出是不同的。
在第二种情况下,看起来一切正常,直到setTimeout
行为止。我的this.setState({ board: newBoard }
尚未更新。你能告诉我为什么吗?
state.board
我通过调用game()得到了什么(预期)
class App extends Component {
constructor(props) {
super(props)
this.state = {
board: [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
],
piece:
[
[1, 0, 0],
[1, 0, 0],
[1, 1, 1]
],
}
}
game = () => {
this.gameID = setTimeout(this.draw, 10);
}
draw = () => this.state.piece.forEach((row, yPos) =>
row.forEach((blockColor, xPos) => {
if (blockColor !== 0) {
const newBoard = this.state.board.map((row, y) => row.map((value, x) => {
if ((y === yPos && x === xPos && blockColor !== 0)) { return value = blockColor }
else { return value }
}));
this.setState({ board: newBoard }, console.log("newBoard ", newBoard, " state.board ", this.state.board));
}
}))
render() {
return (
<Layout>
<div className="game-area">
<Board board={this.state.board} />
</div>
<button type="button" onClick={this.game}>Start</button>
<button type="button" onClick={this.draw}>step</button>
</Layout>
)
}
}
export default App;
我直接调用draw()会得到什么:
0: (10) [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1: (10) [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2: (10) [1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
3: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
4: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
5: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
6: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
7: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
8: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
9: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
10: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
11: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
12: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
13: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
14: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
15: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
16: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
17: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
18: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
19: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0
我的董事会组件
0: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
3: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
4: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
5: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
6: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
7: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
8: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
9: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
10: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
11: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
12: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
13: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
14: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
15: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
16: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
17: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
18: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
19: (10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Layout.js
import React from 'react';
class Board extends React.Component{
render(){
return (
<div>
{this.props.board.map((row,y)=>
row.map((value,x)=>{
const style ={
top: (y*40) , left: (x*40),
backgroundColor: 'red'
}
if(value===0){style.backgroundColor = 'blue'}
else if (value ===1){style.backgroundColor = 'green'}
else if (value ===2){style.backgroundColor = 'yellow'}
//console.log("row: "+row+"x: "+x+"y: "+y);
return(<div className = "block" style = {style}></div>)
})
)}
</div>
);
}}
export default Board;
答案 0 :(得分:1)
setState
可以异步运行。这意味着this.state
在您调用this.setState
之后可能不会立即更新。因此,在更新后引用this.state
是很危险的,因为您将在每次循环迭代中再次引用预更新的数据。另外,setState
会引起更新,并且您不想为响应一个事件而启动多个更新。
我建议您仅执行一个 setState
操作,如下所示:
draw = () => {
let newBoard = this.state.board;
this.state.piece.forEach((row, yPos) => {
row.forEach((blockColor, xPos) => {
if (blockColor !== 0) {
newBoard = newBoard.map((row, y) => row.map((value, x) => {
if ((y === yPos && x === xPos && blockColor !== 0)) {
return value = blockColor
} else {
return value
}
}));
}
})
});
this.setState({
board: newBoard
}, () => {
console.log("newBoard ", newBoard, " state.board ", this.state.board)
});
}