setState无法与React函数中的forloop一起使用

时间:2018-10-19 03:32:03

标签: reactjs

我在componentDidMount内嵌套了两个api调用,一切正常,唯一的问题是状态未更新,所以我放了一些控制台日志以查看发生了什么

fetch reviews done!
analysis done!
false
analysis done!
false
analysis done!
false

您可以看到loaded的状态永远不会更新,并且顺便说一句,没有数据显示在应用程序上,我可能使用此功能弄乱了逻辑,但我无法弄清楚。

 componentDidMount = () => {
    this.setState({ loading: true });
    fetch(
      "https://url-one.com",
      {
        headers: {
          "Content-Type": "application/json",
          "Access-Control-Allow-Origin": "*",
          "X-Spree-Token": "xxx"
        }
      }
    )
      .then(response => response.json())
      .then(responseJson => {
        console.log('fetch reviews done!')
        this.setState(
          {
            list: responseJson.reviews,
          },
          () => {
            var obj = this.state.list;
            var data = [];
            for (let i in obj) {
              fetch(
                "https://url-two.com",
                {
                  method: "POST",
                  headers: {
                    Accept: "application/json",
                    "Content-Type": "application/json"
                  },
                  body: JSON.stringify({
                    api_key: "uuu",
                    data: obj[i].text
                  })
                }
              )
                .then(response => response.json())
                .then(responseJson => {
                  data.push({'review': obj[i].text, 'analysis': responseJson.results * 100});
                });              
              this.setState({
                data: data,
                loaded: true,
                loading: false,
              });
              console.log('analysis done!')
              console.log(this.state.loaded)
            }
          }
        );
      });
  }

当然,如果我使用一个单独的函数来更新它的工作状态,那么!

  show = () => {
    this.setState({ loaded: true });
  };

2 个答案:

答案 0 :(得分:1)

  

如您所见,加载状态永远不会更新

由于setState异步发生(无法立即更新),因此无法像预期的那样使用console.log(this.state.loaded),相反,您可以像使用setState回调一样使用第二个fetch,如下所示:

this.setState(
  {
    data: data,
    loaded: true,
    loading: false
  },
  () => {
    console.log('analysis done!');
    console.log(this.state.loaded);
  }
);

编辑

我认为我们应该使用Promise.all()使其起作用,就像这样:

  componentDidMount() {
    this.setState({ loading: true });
    fetch('https://url-one.com', {
      headers: {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*',
        'X-Spree-Token': 'xxx'
      }
    })
      .then(response => response.json())
      .then(responseJson => {
        console.log('fetch reviews done!');
        this.setState(
          {
            list: responseJson.reviews
          },
          () => {
            var obj = this.state.list;
            var data = [];
            var fetchArr = [];
            for (let i in obj) {
              let promise = fetch('https://url-two.com', {
                method: 'POST',
                headers: {
                  Accept: 'application/json',
                  'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                  api_key: 'uuu',
                  data: obj[i].text
                })
              }).then(response => response.json());

              fetchArr.push(promise);  // make an array of promises
            }

            Promise.all(fetchArr).then(values => {   //after all promises resolved, we'll receive an array of responseJson, we'll loop through it
              values.forEach((responseJson, i) => { //for each responseJson, we push it to the data array
                data.push({
                  review: obj[i].text,
                  analysis: responseJson.results * 100
                });
              });
              // finally, we update state
              this.setState(
                {
                  data: data,
                  loaded: true,
                  loading: false
                },
                () => {
                  console.log('analysis done!');
                  console.log(this.state.loaded);
                }
              );
            });
          }
        );
      });
  }

答案 1 :(得分:0)

您在这里有几个相互冲突的过程,需要加以解决。您不想在异步操作期间修改状态,因为在内部您将触发重新渲染,因此建议您进行一些重组。加载状态无法正确解析,因为您没有等待后续请求完成。这是一个示例:

Edit React and SCSS