ReactJS 错误从 axios 调用 api 获取分配的对象
我有以下代码:
import React, { Component } from 'react';
import axios from 'axios';
class Dashboard extends Component {
state = {
name : 'randomname',
apiData: {}
};
componentDidMount() {
axios.get('https://api_url/getdata)
.then(res => {
const apiData = res.data
this.setState({apiData});
});
}
render() {
const { name, apiData} = this.state;
//THIS WORKS
var objTest = [{game_id: 2}]; //This is returned from apical
console.log(objTest[0].game_id);
console.log(apiData); //logs the following: [{game_id: 2}]
console.log(apiData[0]); //logs the following: {game_id: 2}
console.log(apiData[0].game_id); //Error occurs See error below
return (
<div className="wrap">
TESTING
</div>
);
}
}
export default Dashboard;
在测试并尝试使用
console.log(apiData[0].game_id);
获取 game_id 时,我收到以下错误:
TypeError: undefined is not an object (evaluating 'apiData[0].game_id')
我想知道为什么当我声明一个变量并为其分配与 api 调用返回相同的值时,这会起作用。但是当我将 api 调用分配给 apiData 时,它不起作用。它只能访问返回
{game_id:2
的
apiData[0]
,但无法访问 apiData[0].game_id。
感谢大家的帮助!
这里的主要问题是生命周期方法的顺序。在挂载阶段,先调用构造函数,然后调用渲染方法。ComponentDidMount 尚未调用,因此您的状态为空。记录 apiData 或 apiData[0] 时没有收到错误的原因是,它只是在初始渲染调用(挂载阶段)期间记录空数组或对象,然后在 componentDidMount(更新阶段)之后的第二次渲染期间记录实际对象。但是当您尝试调用属性 (game_id) 时,您会在挂载阶段收到错误 (undefined),因为您在空数组/对象上调用它。
解决方案是在调用父对象上的属性之前检查其是否存在,例如,使用可选链(JS2020 新未来)检查 apiData[0],只需在对象后附加“?”即可修复错误。您也可以对较旧的 JS 使用其他方法。
console.log(apiData[0]?.game_id)
ComponentDidMount 在 render 方法加载后触发。这意味着 console.log(apiData[0]) 在调用 componentDidMount 方法之前首先调用默认状态。
此处的默认状态是一个空对象,而不是数组。因此 apiData 的索引 0 为空。将默认状态更改为
apiData: [{game_id: null}]
将为您提供结果,并且一旦触发 componentDidMount 并成功调用 api,状态就会改变。
然而,这不是最好的方法。它只是为了让事情变得清晰易懂。
只需在状态中定义一个标志,然后检查数据是否可用,一旦获取数据,更改该标志并相应地加载组件元素。
请参阅下面的解决方案以了解您的问题陈述。
import React, { Component } from 'react';
import axios from 'axios';
class Dashboard extends Component {
state = {
loading:true,
name : 'randomname',
apiData: {}
};
componentDidMount() {
axios.get('https://api_url/getdata').then(res => {
this.setState({apiData:res.data, loading:false});
});
}
render() {
const { name, apiData, loading} = this.state;
//THIS WORKS
var objTest = [{game_id: 2}]; //This is returned from apical
console.log(objTest[0].game_id);
console.log(apiData); //logs the following: [{game_id: 2}]
console.log(apiData[0]); //logs the following: {game_id: 2}
console.log(apiData[0].game_id); //Error occurs See error below
return (
<div className="wrap">
{loading ? <div>Loading ...</div> : <div className="wrap">TESTING</div>}
</div>
);
}
}
export default Dashboard;