【问题标题】:data from second fetch API not available in the component来自第二个 fetch API 的数据在组件中不可用
【发布时间】:2019-04-30 02:13:27
【问题描述】:

我正在尝试渲染一个使用 fetch() 调用从 Django REST 框架获取数据的组件。由于我的数据的结构方式,我必须使用 fetch 两次。

当我在收到数据后尝试 setState 并将其传递给组件和 console.log 时,我得到空括号 {},当我展开它时,我有数据但我无法访问它。但是如果我展开它,我可以看到数据

示例: {} 酒店:123, 办公室:456

data.Hotel = 未定义

通常当我控制台记录数据时,它看起来像 {酒店:123,办公室:456}

我构建反应的方式是错误的还是我遗漏了什么? 我是新来的反应,所以任何帮助将不胜感激。

DataProvider.js

import React, { Component } from "react";
import PropTypes from "prop-types";
class DataProvider extends Component {
  static propTypes = {
   endpoint: PropTypes.string.isRequired,
 };

  state = {
      project: {},
      run_set: [],
      project_eui: 0,
      run_euis: {},
      loaded: false,
      placeholder: "Loading.."
    };

  componentDidMount() {
  let currentComponent = this;
  var project = {}
  var run_set = {}
  var project_eui = 0
  var run_euis = {}
  var run_sets = []
  try {
    const data = {username: 'username', password: 'password'};
    fetch('URL', {
      method: 'POST',
      headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
      },
      body: JSON.stringify(data)
    }).then(function(response) {
      return response.json();
    }).then(function(data){
      return data.token
    }).then(function(token){
      try {
        fetch(currentComponent.props.endpoint, {
          method: 'GET',
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
            'authorization': 'Token ' + token
          }
        }).then(function(response) {
          return response.json();
        }).then(function(project){
          project = project
          project_eui = project.eui


          var numBuildingType = project.run_set.length
          for (let i = 0; i < numBuildingType; i++) {
            try {
               //URL from 1st fetch call
              fetch(project.run_set[i], {
                method: 'GET',
                headers: {
                  'Accept': 'application/json',
                  'Content-Type': 'application/json',
                  'authorization': 'Token ' + token
                }
              }).then(function(response) {
                return response.json();
              }).then(function(run_set){
                run_sets.push(run_set)
                run_euis[run_set.building_type] = run_set.eui
              })
            } catch (e) {
              console.log(e);
            }
          }
        })
      } catch (e) {
        console.log(e);
      }
    })
  } catch (e) {
    console.log(e);
  }
  currentComponent.setState({ project: project, project_eui: project_eui, run_set: run_sets, run_euis: run_euis, loaded: true });
}
  render() {
    const { project, project_eui, run_set, run_euis, loaded, placeholder } = this.state
    if (loaded == true) {
      const myJson = { "project": this.state.project, "run_set": this.state.run_set, "project_eui": this.state.project_eui, "run_euis": this.state.run_euis}
      return this.props.render(myJson)
    } else {
      return <p> {placeholder} </p>
    }
  }
}

结构数据.js


...

const StructureData = ({ data }) => {
  console.log(data.run_euis) --------------------> {}
  return (
  <div>
    <p>something</p>
  </div>
);
}

export default StructureData;

App.js

...
return <DataProvider endpoint= {projectApiEndpoint}
                       render= {data => <StructureData data={data} />}
                      />
...

【问题讨论】:

    标签: reactjs fetch-api


    【解决方案1】:

    currentComponent.setState({ project: project, project_eui: project_eui, run_set: run_sets, run_euis: run_euis, loaded: true }); 放错地方了。

    您启动了一个非常复杂的异步 Promise 链,其中涉及 fetch。该代码将需要一些时间才能完成。您不能立即同步使用setState,因为您的fetch 代码仍在运行中。您的setState 呼叫需要在您的fetch 的成功结果.then内部,也许在这里?

                  //URL from 1st fetch call
                  fetch(project.run_set[i], {
                    method: 'GET',
                    headers: {
                      'Accept': 'application/json',
                      'Content-Type': 'application/json',
                      'authorization': 'Token ' + token
                    }
                  }).then(function(response) {
                    return response.json();
                  }).then(function(run_set){
                    run_sets.push(run_set)
                    run_euis[run_set.building_type] = run_set.eui
                    currentComponent.setState({ project: project, project_eui: project_eui, run_set: run_sets, run_euis: run_euis, loaded: true });
                  })
    

    您在控制台中看到的行为是由于当您将对象记录到控制台时,您看到的是它在记录时的值。在这种情况下,您创建一个对象变量,开始一个fetch 调用,然后记录该对象——但此时该对象仍然是空的。但是,当您单击控制台中的“展开”箭头时,它将重新评估该对象并向您显示其新的 current 值 - 这恰好是在 fetch 完成之后。使用console.log 进行调试很容易出现这样的奇怪行为;我建议您习惯使用调试器工具。 https://medium.freecodecamp.org/mutating-objects-what-will-be-logged-in-the-console-ffb24e241e07

    【讨论】:

    • 嘿,这行得通,我明白我做错了什么!谢谢
    • @DaminiGanesh 乐于助人:)
    猜你喜欢
    • 1970-01-01
    • 2018-08-01
    • 2021-10-24
    • 2020-08-01
    • 2016-09-12
    • 2021-01-16
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    相关资源
    最近更新 更多