我在代码中遇到了setState的问题。
尝试
我想要实现的是将所有API调用的结果连接到State中的一个变量。我应该在第一个API中分配所有内容(如在第一个API中的第二个或第三个API调用包装。然后(函数)? ) 要么 我应该单独定义每个api
var requestDigAPI = ...
var requestNEWSAPI =...
并致电
this.setstate({
this.state.articles.concat(dig,buzzfeed)
})
什么是正确的方法?
错误
无论方法反应日志错误。 如果我在第一个API中的其他API中设置State返回
两个API之外的错误buzzfeed unidentified
或setState
错误挖掘,buzzfeed身份不明
componentDidMount() {
this.setState({loading: true})
var apiRequestDig = fetch("api").then(function(response) {
return response.json()
});
var apiRequestNews = fetch("api").then(function(response) {
return response.json()
})
var apiREquestBuzzFeed = fetch(api).then(function(response) {
return response.json()
})
var combinedData = {
"apiRequestDig": {},
"apiRequestNews": {},
"apiREquestBuzzFeed": {}
};
Promise.all([apiRequestDig, apiRequestNews, apiREquestBuzzFeed]).then(function(values) {
combinedData["apiRequestDig"] = values[0];
combinedData["apiRequestNews"] = values[1];
combinedData["apiREquestBuzzFeed"] = values[2];
return combinedData;
});
var dig = apiRequestDig.then(results => {
let dig = results.data.feed.map(article => {
return {
title: article.content.title_alt,
image: article.content.media.images[0].url,
category: article.content.tags[0].name,
count: article.digg_score,
description: article.content.description,
url: article.content.url
}
})
apiREquestBuzzFeed.then(results => {
console.log(results.big_stories[0].title)
let buzzfeed = results.big_stories.map(article => {
return {
title: article.title,
image: article.images.small,
category: article.category,
count: article.impressions,
description: article.description,
url: "https://www.buzzfeed.com"+article.canonical_path
}
})
})
this.setState({
articles: this.state.articles.concat(dig),
loading: "none"
})
// console.log(this.state);
})
}
感谢您的建议
答案 0 :(得分:2)
如何在resolve
的{{1}}回调中移动状态操作代码?
Promise.all
答案 1 :(得分:2)
您可以链接您的API调用,但Promise.all()
允许您进行并发调用,那么为什么不使用它呢?
但是,我认为您的API函数应该在componentDidMount
之外定义,以提高可读性和可重用性:
/* Outside of your component */
const apiRequest = url => fetch(url).then(response => response.json())
const apiRequestDig = () => {
return apiRequest("https://dig/api/url").then(results => {
return results.data.feed.map(article => {
return {
title: article.content.title_alt
/* ... */
};
});
});
};
const apiRequestNews = () => {
return apiRequest("https://news/api/url").then(results => {
return results.big_stories.map(article => {
return {
title: article.title
/* ... */
};
});
});
};
const apiRequestBuzzFeed = () => {
return apiRequest("https://buzzfeed/api/url").then(results => {
return results.big_stories.map(article => {
return {
title: article.title
/* ... */
};
});
});
};
/* Inside your component */
componentDidMount() {
this.setState({loading: true});
Promise.all([
apiRequestDig(),
apiRequestNews(),
apiRequestBuzzFeed()
]).then(values => {
return values[0].concat(values[1], values[2]);
}).then(results => {
this.setState({
articles: this.state.articles.concat(results),
loading: "none"
});
}).catch(err => {
console.log('Oops, something went wrong', err);
});
}
答案 2 :(得分:0)
使用Promise.all将是最好的方法。但请记住Promise.all的失败快速行为,如果一个请求失败,则Promise.all将立即拒绝MDN Link。通过捕获错误并使用空数据解析可以减轻此行为。
function makeAPICall(postId) {
return fetch(`https://jsonplaceholder.typicode.com/posts/${postId}`).then(res => res.json());
}
var Posts = React.createClass({
getInitialState: function() {
return {};
},
componentDidMount: function() {
var requestsArray = [makeAPICall(1), makeAPICall(2), makeAPICall(3)];
Promise.all(requestsArray).then(values => {
var postTitles = values.map(post => post.title).join(", ");
this.setState({
data: postTitles
});
}).catch(console.error.bind(console));
},
render: function() {
return <div>{this.state.data}</div>;
}
});
ReactDOM.render(
<Posts/>,
document.getElementById('root')
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>