javascript - 从多个源异步更新 React 状态

标签 javascript reactjs ecmascript-6 immutability

我正在尝试使用 immutability-helper从多个源(API 调用)异步更新我的 React 状态。然而,在我看来,这不是正确的方法,因为状态总是仅使用来自单一来源的值进行更新。有人可以解释一下为什么会出现这种情况以及如何正确处理我的状态更新吗?

import React from 'react';
import update from 'immutability-helper';

class App extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.state = {
      updateInterval: 60,  // in seconds
      apiEndpoints: [
        '/stats',
        '/common/stats',
        '/personal/stats',
        '/general_info',
      ],
      items: [
        { itemName: 'One', apiUrl: 'url1', stats: {} },
        { itemName: 'Two', apiUrl: 'url2', stats: {} },
      ],
    };
    this.fetchData = this.fetchData.bind(this);
  }

  componentDidMount() {
    this.fetchData();
    setInterval(() => this.fetchData(), this.state.updateInterval * 1000);
  }

  fetchData() {
    this.state.apiEndpoints.forEach(endpoint => {
      this.state.items.forEach((item, i) => {
        fetch(`${item.apiUrl}${endpoint}`)
          .then(r => r.json())
          .then(res => {
            // response from each endpoint contains different keys.
            // assign all keys to stats object and set default 0 to
            // those which don't exist in response
            const stats = {
              statsFromFirstEndpoint: res.first_endpoint ? res.first_endpoint : 0,
              statsFromSecondEndpoint: res.second_endpoint ? res.second_endpoint : 0,
              statsFromThirdEndpoint: res.third_endpoint ? res.third_endpoint : 0,
            };
            this.setState(update(this.state, {
              items: { [i]: { $merge: { stats } } }
            }));
          })
          .catch(e => { /* log error */ });
      });
    });
  }

  render() {
    return (
      <div className="App">
        Hiya!
      </div>
    );
  }
}

export default App;

最佳答案

您应该在 setState 中使用 prevState 参数来确保它始终使用最新状态:

this.setState(prevState =>
  update(prevState, {
    items: { [i]: { $merge: { stats } } },
  }));

或者,将您的请求映射到 promise 数组,然后在所有请求得到解决后setState:

const promises = this.state.apiEndpoints.map(endPoint =>
  Promise.all(this.state.items.map((item, i) =>
    fetch(), // add ur fetch code
  )));
Promise.all(promises).then(res => this.setState( /* update state */ ));

关于javascript - 从多个源异步更新 React 状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50090057/

相关文章:

javascript - 轴按比例正确显示,但图表条未正确绘制

javascript - JQuery/JavaScript 连接每个按键上的输入值

javascript - 如何使用 Typescript 将对象传递给 ReactJS 中的自定义子组件?

javascript - webpack 构建到多个文件

javascript - 流类型不适用于匿名函数内的外部作用域变量

javascript - 传播或休息运营商澄清 ES6

javascript - 文本框中的建议可能吗?

javascript - 根据单击该行中的按钮突出显示或删除该行

javascript - 使用 javascript 生成视频缩略图

javascript - 删除 Javascript 变量中的空格