I have a React app using Redux, redux-thunk, react-router and redux-api-middleware.
In order for a Page component in my app to render, I must access two API endpoints and store their results in the redux store.
Currently, I am dispatching both actions at the same time. This leads to problems when the results of one action complete before the other. So I need to make sure one action completes before I dispatch the second one.
After reading all the documentation I am having trouble understanding how to make this happen with redux-api-middleware.
This is my current component:
class Page extends React.Component {
static prepareState = (dispatch: Function, match: Match) => {
const { params: { projectSlug, menuSlug, pageSlug, env } } = match
if (!projectSlug || !env) {
return
}
dispatch(getSettings(projectSlug, env))
dispatch(getPage(projectSlug, env, menuSlug || '', pageSlug || ''))
}
...
I have tried:
class Page extends React.Component {
static prepareState = (dispatch: Function, match: Match) => {
const { params: { projectSlug, menuSlug, pageSlug, env } } = match
if (!projectSlug || !env) {
return
}
dispatch(
dispatch(getSettings(projectSlug, env))
).then(res => {
console.log('success', res)
dispatch(getPage(projectSlug, env, menuSlug || '', pageSlug || ''))
}).catch(e => {
console.log('failure', e, menuSlug, pageSlug)
})
}
...
But this leads to the catch
being called instead of the then
. However the GET_SETTINGS_SUCCESS action is in fact completed, so I am confused as to why the catch is being called at all. What am I doing wrong?
This is the action generator:
export const getSettings = (projectSlug: string, env: string) => (dispatch: Function, getState: Function) => {
if (getState().settings[env] && loadCompleted(getState().settings.apiState)) {
// already loaded
return
}
dispatch({
[CALL_API]: {
endpoint: settingsUrl(projectSlug, env),
method: 'GET',
credentials: 'include',
types: [{
type: 'GET_SETTINGS',
meta: {projectSlug, env}
}, {
type: 'GET_SETTINGS_SUCCESS',
meta: {projectSlug, env}
}, {
type: 'GET_SETTINGS_FAIL',
meta: {projectSlug, env}
}]
}
})
}
Create a third action called getSettingsThenPage
.
export const getSettingsThenPage = (
projectSlug,
env,
menuSlug = "",
pageSlug = ""
) => dispatch => {
return dispatch(getSettings(projectSlug, env)).then(() => {
return dispatch(getPage(projectSlug, env, menuSlug, pageSlug));
});
};
Invoke that action wherever you must.