I have a draw()
function which updates my state.board
. When i call it through game()
function with setTimeout
, I am getting expected output. But when I try to call it directly, output is different. It looks like in the second case everything works as it should up to this.setState({ board: newBoard }
line. My state.board
is not being updated. Can you please tell me why?
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;
What I get by calling game() (expected)
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
What I get by calling draw() directly:
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]
My Board component
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;
Layout.js
import React from 'react';
import Aux from '../hoc/Aux';
const layout = (props) => (
<Aux>
<div>Toolbar, SidePanel</div>
<main>
{props.children}
</main>
</Aux>
);
export default layout;
setState
may run asynchronously. This means that this.state
may not immediately be updated after you call this.setState
. Thus, referring to this.state
after updating is dangerous, because you'll be referring once again to pre-updated data within each loop iteration. Also, setState
provokes an update, and you don't want to kick off multiple updates in response to one event.
I'd recommend you only do one setState
operation, something like this:
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)
});
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.