直接调用函数绘制时得到不同的输出?反应俄罗斯方块

时间:2019-10-09 19:09:47

标签: javascript reactjs

我有一个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;

1 个答案:

答案 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) 
  });
}