My application allows users to enter data in many different places, and each time I use something like this to call an async thunk:
dispatch(handleDataEntry({ key, value })
In some cases the results of the API call inform the application that another datapoint needs to be set client-side, so the downstream extraReducer
in my slice (using createSlice
from @reduxjs/toolkit
) should now re-dispatch the thunk. But this seems to be an anti-pattern, and in any case I couldn't find a way to do this, so I'm storing sideEffectKey
and sideEffectValue
in state and having components in cases of non-nullity dispatch the thunk themselves.
This doesn't seem like a good solution, and in fact since sideEffectKey
and sideEffectValue
stay non-null until the second API call completes and I can clear them, handleDataEntry
gets dispatched multiple times, causing me problems.
What's a better solution? Is there some way to do something like this?
[handleDataEntry.fulfilled.toString()]: (
state: Store,
action: {
payload: {
sideEffectKey: string | null
sideEffectValue: string | null
}
}
) => {
if (action.payload.sideEffectKey) {
dispatch(handleDataEntry({ key: sideEffectKey, value: sideEffectValue }))
}
}
In your case when you thunk is finish and succeed you dispatch fulfilled
event.
Because create async thunk create actions for theses 3 different states:
By default your thunk cannot listen theses actions dispatched by your other thunk. You need a listener middleware to do it
With listener middleware you can listen to any actions to execute some logic.
You have three different way to listen:
actionCreator
matcher
predicate
In your case you can add a matcher on this to execute handleDataEntry when it has finished.
listenerMiddleware.startListening({
matcher: handleDataEntry.fulfilled,
effect: async (action, listenerApi) => {
if (action.payload.sideEffectKey) {
listenerApi.dispatch(handleDataEntry({ key: sideEffectKey, value: sideEffectValue }))
}
}
},
})
Just be careful on your case you thunk your thunk to call it itself maybe ad a limit. To make sure to do not have an infinite fetch calls
You are right reducers must be pure and should not have side effects.