网格上的forceUpdate警告

时间:2017-08-16 16:48:49

标签: reactjs react-virtualized

当我在这样的网格上强制更新时,我收到以下警告:

proxyConsole.js:56 Warning: forceUpdate(...): Cannot update during an existing state transition (such as within `render` or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to `componentWillMount`.

不确定如何修改放置forceUpdate()的位置以使其正常运行。

const quoteList = [];

class App extends Component {
  constructor() {
    super();
    this.state = {
      response: {},
      endpoint: "http://127.0.0.1:4001"
    };
  }

  componentDidMount() {
      const { endpoint } = this.state;
      const socket = socketIOClient(endpoint);
      this.theGrid.forceUpdate();

      socket.on("FromAPI", data =>  this.setState({ response: data }));
  }

  cellRenderer ({ columnIndex, key, rowIndex, style }) {
      return (
        <div
          key={key}
          style={style} 
        >
          {quoteList[rowIndex][columnIndex]}
        </div>
      )  
  }

  render() {
      const { response } = this.state;


      if(Object.keys(response).length !== 0)
      {
        //console.log(response);

        const row = symbolRowDictionary[response.ticker];
        var column = 0;

        switch(response.type)
        {
          case 'bid':
            column = 1;
            break;
          case 'ask':
            column = 3;
            break;
          case 'last':
            column = 5;
            break;
          default:
            console.log('Unknown type');
        }

        quoteList[row][column] = response.size;
        quoteList[row][column + 1] = response.price;
        this.theGrid.forceUpdate();
      }

      return (
        <div style={{ textAlign: "center" }}>
        {
          <ul><li>Quote: {response.ticker} {response.type} {response.price} {response.size}</li></ul>           
        }

        <div>
          &nbsp;
        </div>

        <Grid
            ref={(ref) => this.theGrid = ref}
            cellRenderer={this.cellRenderer}
            columnCount={7}
            columnWidth={75}
            height={quoteList.length * 20}
            rowCount={quoteList.length}
            rowHeight={20}
            width={800}
        /> 

        </div>
      );
    }
}

export default App;

2 个答案:

答案 0 :(得分:0)

我会将quoteList移动到组件state,如下所示:

&#13;
&#13;
const endpoint: "http://127.0.0.1:4001";

class App extends Component {
  constructor() {
    super();
    this.state = {
      response: {},
      quoteList = [];
    };
  }

  componentDidMount() {
    const socket = socketIOClient(endpoint);
    let _this = this;
    let {quoteList} = this.state;
    socket.on("FromAPI", data =>  { 
      if(Object.keys(response).length !== 0) {
        const row = symbolRowDictionary[response.ticker];
        var column = 0;
        switch(response.type)
        {
          case 'bid':
            column = 1;
            break;
          case 'ask':
            column = 3;
            break;
          case 'last':
            column = 5;
            break;
          default:
            console.log('Unknown type');
        }

        quoteList[row][column] = response.size;
        quoteList[row][column + 1] = response.price;
        _this.setState({ response: data, quoteList: quoteList })
      }    
    }));
  }

  cellRenderer ({ columnIndex, key, rowIndex, style }) {
    let {quoteList} = this.state;
    return (
      <div
        key={key}
        style={style} 
      >
        {quoteList[rowIndex][columnIndex]}
      </div>
    )  
  }

  render() {
    const { response, quoteList } = this.state;
    
    return (
      <div style={{ textAlign: "center" }}>
        {
          <ul><li>Quote: {response.ticker} {response.type} {response.price} {response.size}</li></ul>           
        }
        <div>
          &nbsp;
        </div>
        <Grid
            ref={(ref) => this.theGrid = ref}
            cellRenderer={this.cellRenderer}
            columnCount={7}
            columnWidth={75}
            height={quoteList.length * 20}
            rowCount={quoteList.length}
            rowHeight={20}
            width={800}
        /> 

      </div>
    );
  }
}

export default App;
&#13;
&#13;
&#13;

更新quoteList后,其length将相应更新,这些更改将传递给子组件Grid

修改

由于你不明白为什么这个代码运行,我会解释一下。如果您不了解React生命周期,请查看此illustration

  1. quoteListconstructor
  2. 中初始化为空数组
  3. render是第一次被召唤。 cellRenderer将绑定到此组件,或this指向App组件。
  4. 安装组件后,将触发componentDidMount。这是我们应该从API获取数据的时间。在功能块(data => {...})内,this指向函数本身。因此,在获取API之前,我必须指定_this = this才能调用setState
  5. setState已执行,render将再次触发,因为quoteList已更改。根据新App,您的quoteList将以不同方式呈现。表示新的quoteList现已传递到您的GridGrid也会重新渲染。
  6. 通过此流程,您不需要forceUpdate

答案 1 :(得分:0)

经过大量实验和一些在线文档后,我能够通过这样设置this.theGrid.forceUpdate来解决它。没有任何警告,renderrendercell保持纯正&#34;

componentDidMount() {
      const socket = socketIOClient(endpoint);

      socket.on("FromAPI", data => 
        {
          this.setState({ response: data });
          this.theGrid.forceUpdate();
        }
      );
  }