javascript - 在 SocketIO 事件监听器中调用 setState 后 React Component 未更新

标签 javascript node.js reactjs socket.io

我有一个类组件。我在构造函数中添加了这一行:

this.handleChangedCells = this.handleChangedCells.bind(this);

我在 componentDidMount 中注册了一个 SocketIO 监听器并调用了这样一个函数

socket.on("changedCells", this.handleChangedCells);

我正在接收数据,因为我会在收到数据后进行控制台记录。问题是该函数调用了 this.setState 并且它没有更新组件。我有

handleChangedCells(data) {
    console.log(data);
    let new_board = this.state.board;
    data.map(arr => {
      arr.map(obj => {
        new_board[obj.ind[0]][obj.ind[1]] = {
          color: obj.color,
          alive: obj.alive
        };
      });
    });

    this.setState({ board: new_board });
}

我的组件如下:

render() {
    return (
      <div className="boardContainer" style={container_style}>
        {this.state.board.map((row, r_ind) => {
          return (
            <div className="row" key={r_ind}>
              {row.map((col, c_ind) => {
                return (
                  <Cell
                    key={[r_ind, c_ind]}
                    cell_row_index={c_ind}
                    cell_col_index={r_ind}
                    socketProps={socket}
                    colorProps={this.state.color}
                    clickedColorProps={col.color}
                    aliveProps={col.alive}
                  />
                );
              })}
            </div>
          );
        })}
      </div>
    );
  }

如您所见,该组件取决于我更新的状态,但是,该组件未更新...知道这里发生了什么吗?

编辑:这是我项目的链接 https://github.com/Dobermensch/ExpressTest.git有问题的文件是/client/components/Game.js

编辑 2:board 是一个包含对象 {color: [x,y,z], alive: boolean} 的数组,我正在获取更改的单元格(死单元格)和标记他们在董事会中死了所以理想情况下我会去死细胞的索引并通过 board[row][col] = {color: [x,y,z], alive: false} 将其标记为死

编辑 3:board 的数据结构是 [[{}.{},{}],[{},{},{}]] 我正在更改其中对象的属性数组

最佳答案

我在组合使用嵌套对象数组 时遇到过类似的问题。我认为 setState 不能很好地处理嵌套更新。

另一个问题在您的代码中。您实际上是在改变 state

let new_board = this.state.board; 这里的棋盘是一个数组。 Javascript 不会深度克隆arrayobject。您正在将 board arrayrefererence 分配给新变量。

所以,您可以做的只是深度克隆数组

let new_board = this.state.board.map(item => {...item}); // You may need to handle the multiple levels.

JSON.stringyJSON.parse 也应该可以工作。

let new_board = JSON.parse(JSON.stringify(array));

曾经,您拥有状态深度克隆。您可以修改数据,setState 应该会触发重新渲染。

更新 1:

因为您正在使用 Cell 的状态来更新它。 Prop 值不会在重新渲染时更新。

所以你应该使用getDerivedStateFromProps在您的 Cell 组件中使 prop 数据可用于 state

static getDerivedStateFromProps(props, state) {
    return {
      r: props.clickedColorProps[0],
      g: props.clickedColorProps[1],
      b: props.clickedColorProps[2],
      alive: props.aliveProps
    };
  }

注意 getDerivedStateFromProps 将在组件的每次重新渲染时执行,即使状态发生变化。因此,您应该在方法中设置条件以返回正确的数据。

关于javascript - 在 SocketIO 事件监听器中调用 setState 后 React Component 未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58407283/

相关文章:

javascript - XMLHttpRequest:如何强制缓存?

javascript - 动态向 Laravel 表单添加字段

javascript - Meteor添加中间件方法的差异

javascript - 如何将对象从 pug 传递到前端 javascript

javascript - 无法从子状态正确初始化父组件中的状态

javascript - 在一个屏幕上添加多个 HighCharts Angularjs

javascript - JQuery 如何处理文件

node.js - NestJS项目架构: how to avoid dependencies between modules

css - 使用导入模块中的变量时 SASS 'Invalid css error'

javascript - net::ERR_CONNECTION_REFUSED 到cube.dv