所以,我陷入了React的困境,这已经让我抓狂了。
我正在获取一些API数据,并试图访问任何特定的索引或进行遍历-无论我做什么,它似乎都无法正常工作!
这是主要组成部分:
class App extends React.Component {
const CityListNames = ['Peterborough', 'Manchester', 'Brighton', 'Liverpool', 'Cardiff'];
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
items: []
};
}
// Fire our function below on app load
componentDidMount() {
this.getWeather();
}
// getWeather - make api call
getWeather = () => {
let results = [];
// Loop through our cities list here to gather data
// We will then push this into this.state.results
CityListNames.forEach(function (name) {
let api_url = "http://api.openweathermap.org/data/2.5/weather?q="+name+",UK&appid="+ApiKey;
let data;
// get api data
fetch(api_url)
.then(res => res.json())
.then(
(result) => {
results.push(result);
console.log(result[0]);
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
);
});
this.setState({
isLoaded: true,
items: results
});
}
render() {
const { error, isLoaded, items } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className="weather-app">
</div>
);
}
}
}
export default App;
当我使用console.log(result[0]);
时,它只是在控制台中输出为“ undefined”。
我试图将所有值分配给结果变量,然后将其推入状态。
当我执行console.log(items)时,它也会显示所有项目,这很奇怪。
API数据
任何帮助将不胜感激!
谢谢
答案 0 :(得分:1)
您的意思是console.log(results [0])的'结果'的复数。在您的Promise结果中,是解析对json的响应后得到的结果。如果该响应的键名不为“ 0”(不应该为0),则您将不确定。
修改
问题不在于您正在进行异步调用,然后执行push和console.log的同步操作。问题在于您在控制台日志记录与推送正确响应之间存在错字。
fetch(api_url)
.then(res => res.json())
.then(
(result) => {
results.push(result); // <--- pushes valid response into array
console.log(result[0]); // <--- logs undefined
},
响应没有键“ 0”,因此您登录时未定义,但会推送结果(有效)。因此,您将在通话结束时得到一系列正确的结果。但是您将记录一堆“未定义”来进行控制台。
答案 1 :(得分:1)
在设置状态之前,您必须等待所有api请求解决,因此不要使用forEach,而是使用map,然后返回日期承诺,如下所示:
getWeather = () => {
// Loop through our cities list here to gather data
// We will then push this into this.state.results
Promise.all(CityListNames.map(function (name) {
let api_url = "http://api.openweathermap.org/data/2.5/weather?q="+name+",UK&appid="+ApiKey;
return fetch(api_url)
.then(res => res.json());
})).then((results) => {
this.setState({
isLoaded: true,
items: results
});
}).catch((error) => {
this.setState({
isLoaded: true,
error
});
});
}
答案 2 :(得分:1)
尝试一下。
class App extends React.Component {
const CityListNames = ['Peterborough', 'Manchester', 'Brighton', 'Liverpool', 'Cardiff'];
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
items: []
};
}
// Fire our function below on app load
componentDidMount() {
this.getWeather();
}
// getWeather - make api call
getWeather = () => {
let self = this,
results = [], responses = [];
// Loop through our cities list here to gather data
// We will then push this into this.state.results
CityListNames.forEach(function (name) {
let api_url = "http://api.openweathermap.org/data/2.5/weather?q="+name+",UK&appid="+ApiKey;
let data;
// get api data
fetch(api_url)
.then(res => {
responses.push(res.json());
});
};
Promise.all(responses).then((values) => {
self.setState({
isLoaded: true,
items: results
});
});// this works, because setState is called after before all promises are fulfilled
}
render() {
const { error, isLoaded, items } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className="weather-app">
</div>
);
}
}
}
export default App;
答案 3 :(得分:0)
1.fetch:异步工作,因此,当您将状态值赋给状态时,它将是一个空数组。
this.setState({
isLoaded: true,
items: results
});
先前的代码必须包含在获取结果中
class App extends React.Component {
cityListNames = ['Peterborough', 'Manchester', 'Brighton', 'Liverpool', 'Cardiff']; // this is one of the changes
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
items: []
};
}
componentDidMount() {
this.getWeather();
}
getWeather = () => {
let results = [];
this.cityListNames.forEach(function (name) { //this is one of the changes
let api_url = "http://api.openweathermap.org/data/2.5/weather?q="+name+",UK&appid="+ApiKey;
let data;
fetch(api_url)
.then(res => res.json())
.then((result) => {
results.push(result);
this.setState({ // this is one of the changes
isLoaded: true,
items: results
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
);
});
}
render() {
const { error, isLoaded, items } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className="weather-app">
</div>
);
}
}
}
export default App;