尝试从“ this.state”中的JSON对象读取信息时发生未定义的错误。
组件类:
class App extends Component {
state = {}
// Code is invoked after the component is mounted/inserted into the DOM tree.
componentDidMount() {
const url = 'http://datapoint.metoffice.gov.uk/public/data/val/wxfcs/all/json/APIKEY'
fetch(url)
.then(response => {return response.json()})
.then(data => {
this.setState(data)
})
}
render() {
console.log(this.state.SiteRep.DV)
return <p>TEXT</p>
}
}
export default App
Json对象:
{
"SiteRep": {
"Wx": {
"Param": [
{
"name": "FDm",
"units": "C",
"$": "Feels Like Day Maximum Temperature"
},
{
"name": "FNm",
"units": "C",
"$": "Feels Like Night Minimum Temperature"
},
...
]
},
"DV": {
"dataDate": "2019-10-09T13:00:00Z",
"type": "Forecast",
"Location": {
"i": "354287",
"lat": "52.0951",
"lon": "1.3143",
"name": "WOODBRIDGE",
"Period": [
{
"type": "Day",
"value": "2019-10-09Z",
"Rep": [
{
"D": "W",
"Gn": "22",
"Hn": "66",
"PPd": "8",
...
},
{
"D": "WSW",
"Gm": "22",
"Hm": "87",
"PPn": "1"
}
]
},
{
"type": "Day",
"value": "2019-10-10Z",
"Rep": [
{
"D": "WSW",
"Gn": "29",
"Hn": "61",
"PPd": "5",
},
{
"D": "SW",
"Gm": "34",
"Hm": "87",
"PPn": "19",
}
]
}
...
]
}
}
}
}
我将映射“ Period”列表以映射某些元素,但是当尝试访问“ this.state”中的对象的所述部分时,遇到错误“无法读取属性” DV 'of undefined'
在状态内找到该对象,所有Json数据均正确,并且当我不在'.SiteRep'对象之外时,可以在控制台中访问它。觉得我做错了什么:D
答案 0 :(得分:0)
这是生命周期问题。加载组件后ComponentDidMount
触发,这意味着this.state.SiteRep.DV
尚不存在。您需要添加检查以查看SitRep
上是否存在state
,以便不会出错。
所以...
if(this.state.hasOwnProperty('SiteRep') console.log(this.state.SiteRep.DV)
这是组件的预期行为:
First render happens
=> `ComponentDidMount` is fired
=> Request is made and response is set to state
=> setState triggers another render where SiteRep does exist on state
然后使用您的JSX:
render() {
if(this.state.SiteRep && this.state.SiteRep.DV) {
return <p>interpolate a value from {this.state.SiteRep.DV.someStringProp} </p>
}
return null
}
答案 1 :(得分:0)
这里的问题是,尽管您的Json位于componentDidMount
中,但是render()
发生在获取完成之前。只需在访问数据之前检查数据是否可用即可解决您的问题。
class App extends Component {
state = {}
// Code is invoked after the component is mounted/inserted into the DOM tree.
componentDidMount() {
const url = 'http://datapoint.metoffice.gov.uk/public/data/val/wxfcs/all/json/APIKEY'
fetch(url)
.then(response => {return response.json()})
.then(data => {
this.setState(data)
})
}
render() {
if(this.state.SiteRep){
console.log(this.state.SiteRep.DV);
}
return <p>TEXT</p>
}
}
export default App
答案 2 :(得分:0)
请考虑再经历一次React的组件生命周期here。
这就是您的代码中发生的事情:
render()
方法(在这里您不需要数据)。componentDidMount()
在初始render()
之后被调用,您在其中进行API调用并使用响应数据更新状态。解决此问题的一种方法-
isFetching
的标志true
最初设置为state = { isFetching: true };
。 render()
isFetching
方法以显示后备UI,直到您的API调用成功,即...
render() {
const { isFetching } = this.state;
if (isFetching) {
return <span> Fetching data </span>;
}
console.log(this.state.SiteRep.DV)
return <p>TEXT</p>
}
...
为假; isFetching
...
componentDidMount() {
// You're going to call the API now, set isFetching to true
this.setState({ isFetching: true });
const url = 'http://datapoint.metoffice.gov.uk/public/data/val/wxfcs/all/json/APIKEY'
fetch(url)
.then(response => {return response.json()})
.then(data => {
// API call done, set data and make isFetching false.
this.setState({ data, isFetching: false });
})
}
...
标志:
state = {
SiteRep: {
DV: {}
}
}
另一种方法是添加初始状态,例如:
render()
使用这种方法,最初您将看不到任何数据,但是在组件状态下更新API响应后,组件将重新呈现。
我个人会采用第一种方法,因为您可以更好地控制自己的let scores = [{name: "A", skills: 500, result: 80},
{name: "B", skills: 6000, result: 90},
{name: "C", skills: 6000, result: 60},
{name: "D", skills: 20, result: 60},
{name: "E", skills: 10, result: 90}];
const maxSkill = scores.reduce((acc, curr) => curr.skills > acc ? curr.skills : acc, 0);
const maxResult = scores.reduce((acc, curr) => curr.result > acc ? curr.result : acc, 0);
const maxSkillsAndRes = scores.reduce((r, o) => (o.skills === maxSkill || o.result === maxResult) ? [...r,o] : r, []);
console.log(maxSkillsAndRes);