来自第二次提取的数据 API 在组件中不可用
data from second fetch API not available in the component
我正在尝试呈现一个组件,该组件使用 fetch() 调用从 Django 休息框架获取数据。由于我的数据结构方式,我必须使用 fetch 两次。
当我在收到数据并将其传递给一个组件并 console.log 它后尝试设置状态时,我得到空括号 {} 并且当我展开它时我有数据但我无法访问它。但是如果我展开它,我可以看到数据
示例:
{}
酒店:123,
办公室:456
data.Hotel = 未定义
通常当我 console.log 数据看起来像
{酒店:123, Office: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>
}
}
}
StructureData.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} />}
/>
...
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
调用,然后记录了该对象——但此时该对象仍然是空的。但是,当您单击控制台中的 "expand" 箭头时,它将重新评估该对象并向您显示其新的 current 值——恰好在 fetch
已经完成。使用 console.log
进行调试可能会出现类似的奇怪行为;我建议您习惯使用调试器工具。 https://medium.freecodecamp.org/mutating-objects-what-will-be-logged-in-the-console-ffb24e241e07
我正在尝试呈现一个组件,该组件使用 fetch() 调用从 Django 休息框架获取数据。由于我的数据结构方式,我必须使用 fetch 两次。
当我在收到数据并将其传递给一个组件并 console.log 它后尝试设置状态时,我得到空括号 {} 并且当我展开它时我有数据但我无法访问它。但是如果我展开它,我可以看到数据
示例: {} 酒店:123, 办公室:456
data.Hotel = 未定义
通常当我 console.log 数据看起来像 {酒店:123, Office: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>
}
}
}
StructureData.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} />}
/>
...
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
调用,然后记录了该对象——但此时该对象仍然是空的。但是,当您单击控制台中的 "expand" 箭头时,它将重新评估该对象并向您显示其新的 current 值——恰好在 fetch
已经完成。使用 console.log
进行调试可能会出现类似的奇怪行为;我建议您习惯使用调试器工具。 https://medium.freecodecamp.org/mutating-objects-what-will-be-logged-in-the-console-ffb24e241e07