My React component needs to fetch some data A asynchronously, and then based on its contents, send a second async request to get data B. All result are stored in Redux and we use Redux-thunk.
There may be several components on the page at the same time that all need A, so there' s a good chance that it already exists n Redux; but another component could also be fetching it, and then isFetching is true. I don't want to have multiple identical requests (not least because the browser cancels them).
Solutions for sequential actions like https://github.com/reactjs/redux/issues/1676 and https://github.com/reactjs/redux/issues/723 propose a redux-thunk that returns a promise, one that is already resolved if the object is already present; e.g.:
function getA(uuid) {
return (dispatch, getState) => {
const currentA = getState().a[uuid];
if (currentA) {
// Return resolved promise with the already existing object
return Promise.resolve(currentA);
} else {
// Return async promise
return goFetchA(uuid).then(objectA => {
dispatch(receivedA(uuid, objectA));
return objectA;
});
}
};
}
function getAthenB(uuidA, uuidB) {
return dispatch =>
dispatch(getA(uuidA)).then(
objectA => dispatch(getB(objectA, uuidB)));
}
So far, so good. But what kind of promise can I return in case the state contains both the object and an 'isFetching' boolean? This would be trivial if we could store the actual Promise of the request in the state, but that sort of thing shouldn't go into a Redux state.
function getA(uuid) {
return (dispatch, getState) => {
const currentA = getState().a[uuid];
if (currentA) {
if (!currentA.isFetching) {
return Promise.resolve(currentA.data);
} else {
// WHAT TO RETURN HERE?
}
} else {
dispatch(startFetchingA(uuid));
return goFetchA(uuid).then(objectA => {
receivedObjectA(uuid, objectA);
return objectA;
});
}
};
}
A similar problem exists when I want to cancel an ongoing request -- it's not stored anywhere, so a solution that also helps with that would be ideal.
getA, in the thunk function(dispatch, getState) => { ... }, why are non-actions being returned? It seems like you should instead calldispatchwith the promise/objectA in an action object.