代码之家  ›  专栏  ›  技术社区  ›  Nick Kinlen

React-使用componentDidUpdate根据从另一个函数传递的数据更新状态

  •  0
  • Nick Kinlen  · 技术社区  · 6 年前

    我正在学习React,并在开发一款JohnConway的游戏应用程序。我在state/constructor中定义了一个2D数组,它创建了一个正方形的游戏板。我有一个函数叫做 isSquareAlive selectBoardSize 它允许用户点击一个按钮并调整电路板的大小。

    当应用程序挂载时,我会生成一个随机的棋盘,其中有些方块被设置为“活动”,有些则不是。我在里面处理这个 componentDidMount :

      componentDidMount = () => {
        const data = this.state.board;
        // Creates random decimal number between 0 and 1
        const startingBoard = data.map(a => a.map(Math.random));
        // Rounds decimal numbers to either 0 or 1 so the grid can display whether the cell is alive or dead
        const rounded = startingBoard.map(a => a.map(Math.round));
    
        this.setState({
           board: rounded
        });
      }
    

    这个很好用。如果用户试图通过 选择BoardSize 选择BoardSize :

      // Allows user to click button and change size of game board
      selectBoardSize = (width, height) => {
        this.setState({
          boardHeight: height,
          boardWidth: width,
          board: Array(this.state.boardHeight).fill(0).map(_ =>
                  Array(this.state.boardWidth).fill(0))
        });
          {/*this.onChangeBoardSize(width, height);*/}
      }
    

    当用户改变我试图使用的电路板尺寸时 componentDidUpdate 获取新的电路板尺寸并用随机的“活动”单元填充该电路板尺寸,就像我最初使用 组件安装 . 这就是我遇到的困难。

    组件更新

      // Attempts to fill board with random alive squares when user resizes the size of the board via onClick/selectBoardSize()
      componentDidUpdate = (prevProps, prevState) => {
        console.log('PrevState is : ' + prevProps, prevState);
    
        // Attempts to update board height and width and then populate board with random "alive" squares
        if(this.state.boardWidth !== prevState.boardWidth) {
          if(this.state.boardHeight !== prevState.boardHeight) {
            // Console.log runs, if statements equate to true when user resizes board
            console.log('Nested if statements in componentDidUpdate triggered');
    
            const boardWidth = this.state.boardWidth;
            const boardHeight = this.state.boardHeight;
            const data = this.state.board;
            // Creates random decimal number between 0 and 1
            const startingBoard = data.map(a => a.map(Math.random));
            // Rounds decimal numbers to either 0 or 1 so the grid can display whether the cell is alive or dead
            const rounded = startingBoard.map(a => a.map(Math.round));
    
            this.setState({
              boardWidth: boardWidth,
              boardHeight: boardHeight,
              board: rounded
            })
          }
        }
      }
    

    当用户点击按钮调整尺寸时,电路板成功地改变了尺寸,但它不会像应该的那样生成随机的“活动”正方形。它只是改变了板的高度和宽度,但板是空的。

    我怎么用 组件更新 当游戏板调整大小时,用随机的“活动”单元格填充游戏板(类似于最初安装时所做的操作,但当游戏板改变大小时大小会适当调整)。是 组件更新 正确的方法?这是setState异步的问题吗?

    我肯定我想得太多了。

    你可以在网上查到密码 codesandbox

    1 回复  |  直到 6 年前
        1
  •  2
  •   Alexandre Wiechers Vaz    6 年前

    你不需要使用 componentDidUpdate 为了这个,稍后再谈。

    这不起作用,因为你(对了,顺便说一句)把你的 componentDidMount 将to编码为两个条件,以检查 boardWidth boardHeight 确实变了。问题是,高度永远不会改变,所以它永远不会到达代码的这一部分。

    我了解到,每次用户更改大小时,您都要执行以下操作:

    • 根据所需的宽度和高度创建新板;

    onChangeBoardSize 功能,稍有改动。 请注意,您不需要从state中检索board,因为它将过时,具有旧的宽度和高度;

    onChangeBoardSize = (width, height) => {
      // Recreate board with new width and height values
      const data = Array(height)
        .fill(0)
        .map(_ => Array(width).fill(0));
      // Creates random decimal number between 0 and 1
      const startingBoard = data.map(a => a.map(Math.random));
      // Rounds decimal numbers to either 0 or 1 so the grid can display whether the cell is alive or dead
      const rounded = startingBoard.map(a => a.map(Math.round));
    
      this.setState({
        boardHeight: height,
        boardWidth: width,
        board: rounded
      });
    };
    

    Codesandbox example

    提示:注意子序列状态修改过多。总是喜欢一次完成,而不是按顺序触发setState。特别是生命周期方法