反应数据获取-两阶段更新

时间:2019-03-07 19:45:44

标签: javascript reactjs

我是新来的反应者,完全坚持这一点。

说我有一个具有以下结构的简单应用程序:

<App>
|___<Container>
    |___<Chart>

<App>的某个地方,我有一个事件,该事件会修改<Container>的道具,然后根据这些道具将<Container>中的查询方法触发到数据库,这需要一定的时间。时间量(例如1秒)。查询返回后,它将修改<Container>的状态,特别是进入<Chart>属性的数据属性。

现在说,我希望<Chart>能够看到<App>的旧道具和新道具之间发生了什么变化(假设这些道具也一直传递到<Chart>)。我们得到的是:

应用事件->修改应用状态->根据道具更新容器->触发查询

但是我可以在哪里放置“火灾查询”功能?如果我在ComponentDidUpdate中这样做,则意味着我丢失了先前的道具,因为查询修改了<Container>的状态,从而第二次更新了<Chart>,这意味着第二次更新了'prevProps' <App>元素中的事件之后,道具将已经更新。

我在这里可以做什么?我在这里看不到如何使用shouldComponentUpdate,因为那会在更新之前触发,并且我需要触发'update'事件,以便<Container>元素有理由在事件发生后重新获取数据。 <App>

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:0)

在道具与状态之间似乎有些混乱。将状态视为该组件的私有状态。容器的更新状态并不意味着道具已更改。

想想电灯开关。状态为开或关。但是,家庭设计师可能已经定义了某些属性,并将它们围绕颜色和形状等内容传递给室内设计团队。这些是分开的。

关键是电灯开关可以处于打开或关闭状态,这不会改变电灯开关的属性。

在您的示例中,道具历史可以作为容器状态的一部分进行跟踪。

class Container extends React.Component {
  constructor(props) {
    super(props);
    
    this.state = {
      data: [
        [Math.random(), Math.random(), Math.random()]
      ]
    }
  }

  componentDidMount() {
    setInterval(() => this.setState({ 
      data: [
        ...this.state.data, 
        [Math.random(), Math.random(), Math.random()]
      ]
    }), 5000)
  }
  
  render() {
    return (
      <Chart data={this.state.data} />
    );
  }
}

class Chart extends React.Component {  
  render() {
    const data = this.props.data.slice(-2);
    
    const previousDataSum = (data[0] || []).reduce((total, current) => total + current, 0);
    const currentDataSum = (data[1] || []).reduce((total, current) => total + current, 0);
    
    
    
    return (
      <div>
        <div>
          PrevPropsSum: {previousDataSum}
        </div>
        <div>
          CurrentPropsSum: {currentDataSum}
        </div>
        <div>
          Difference: {previousDataSum && currentDataSum ? previousDataSum - currentDataSum : 0}
        </div>
      </div>
    )
  }
}

ReactDOM.render(<Container />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>