Reputation: 117
What's the best approach to using the results of one fetch request to make another fetch request to a different endpoint? How can I confirm the first fetch has completed and setState has happened?
class ProductAvailability extends React.Component {
state = {
store_ids: []
}
componentDidMount() {
fetch(`myapi.com/availability?productid=12345`)
.then((results) => {
return results.json();
})
.then((data) => {
const store_ids = data.result.map((store) => {
return store.store_id
})
this.setState({store_ids: store_ids})
})
/* At this point I would like to make another request
to myapi.com/storedata endpoint to obtain information
on each store in the state.store_ids, and add details
to the state */
}
render() {
return (
<div>
<p>STORE INFO FROM STATE GOES HERE</p>
</div>
)
}
}
Upvotes: 1
Views: 1164
Reputation: 19772
Easier to do with async/await
(.then/.catch
requires a bit more work -- also, reference to Bluebird's Promise.each function). For clarity, its best to move this out of componentDidMount
and into its own class method.
As a side note, if this action is happening for every product, then this secondary query should be handled on the backend. That way, you only need to make one AJAX
request and retrieve everything you need in one response.
componentDidMount = () => this.fetchData();
fetchData = async () => {
try {
const productRes = fetch(`myapi.com/availability?productid=12345`) // get product data
const productData = await productRes.json(); // convert productRes to JSON
const storeIDs = productData.map(({store_id}) => (store_id)); // map over productData JSON for "store_ids" and store them into storeIDs
const storeData = [];
await Promise.each(storeIDs, async id => { // loop over "store_ids" inside storeIDs
try {
const storeRes = await fetch(`myapi.com/store?id=${id}`); // fetch data by "id"
const storeJSON = await storeRes.json(); // convert storeRes to JSON
storeData.push(storeJSON); // push storeJSON into the storeData array, then loop back to the top until all ids have been fetched
} catch(err) { console.error(err) }
});
this.setState({ productData, storeData }) // set both results to state
} catch (err) {
console.error(err);
}
}
Upvotes: 0
Reputation: 2478
When you do setState, it updates the component, so the natural point to read state after you've done a setstate, if you'd have read the docs, is in componentDidUpdate(prevProps, prevState). I leave you to the doc: https://reactjs.org/docs/react-component.html#componentdidupdate Attention: Don't use willupdate, it's unsafe as you read in the docs.
A further consideration could be done. If you could avoid to put these data in the state, you could also do everything in the componendDidMount (with promiseall for all the other requests maybe) and then set the state with the old and new data, this is preferable since you update your component only once.
Upvotes: 1