Reputation: 1570
I am trying to make synchronous dispatch calls in Redux where the first call updates a isLoading
state so that we can show a loading icon on the UI and then the second call does a lot of synchronous calculations behind the scenes to update item positions - takes about 2-5 seconds.
The first action happens and the state is changed correctly, but it appears that immediately after that happens it doesn't hit the react front-end components, but it goes to the second dispatch. It works when I add in a short timeout
after the first dispatch, but I hate to hardcode a fixed wait time.
Is there a better solution to this issue?
NOT WORKING:
const showLoadingIcon = () => ({type: types.SHOW_LOADING_ICON});
export const updateInteractionTypeScores = (updatedValues) => dispatch => {
dispatch(showLoadingIcon());
dispatch({type: types.UPDATE_VALUES, updatedValues});
};
WORKING:
const showLoadingIcon = () => ({type: types.SHOW_LOADING_ICON});
export const updateInteractionTypeScores = (updatedValues) => dispatch => {
dispatch(showLoadingIcon());
setTimeout(() => dispatch({type: types.UPDATE_VALUES, updatedValues}), 100);
};
Upvotes: 2
Views: 2204
Reputation: 8895
What you call a synchronous action really is an asynchronous action, with updates of the store at specific times. The general pattern for things like that is to have (at least) three dispatches for each of the states of the action.
Launching the asynchronous action dispatches a "ASYNC_ACTION_LAUNCHED" action, which updates the store, to which your components are correctly connected (right?) hence will show the loading icon.
Upon success, an "ASYNC_ACTION_SUCCESS" is dispatched, the store is updated, the component rerenders with the new store content.
Upon failure, an "ASYNC_ACTION_FAILURE" is dispatched, the store is updated, the component rerender with empty content and an error message.
In practice, this amounts to more code, but this allows for much more possibilities:
const asyncActionLaunched = () => ({type: types.ASYNC_ACTION_STARTED});
const asyncActionSuccess = () => ({type: types.ASYNC_ACTION_SUCCESS});
const asyncActionFailed = () => ({type: types.ASYNC_ACTION_FAILED});
export const updateInteractionTypes = dispatch => {
dispatch(asyncActionLaunched());
// I don't know your setup
// But this whould either be a Promise, or return a boolean
// in the case of a synchronous function
const result = makeSynchronousCalculations();
if (result) {
dispatch(asyncActionSuccess());
// dispatch another action that updates store
} else {
dispatch(asyncActionFailed());
// dispatch another action that updates store
}
// in the case of a promise
asyncBlockingAction()
.then(
dispatch(asyncActionSuccess());
// dispatch another action that updates store
).catch(
dispatch(asyncActionFailed());
// dispatch another action that updates store
);
};
Upvotes: 1