armaka
armaka

Reputation: 264

createListenerMiddleware to trigger when extraReducer has job done?

I have a Redux createListenerMiddleware defined in store.ts:

export const listenerMiddleware = createListenerMiddleware()

listenerMiddleware.startListening({
    actionCreator: myAction,
    effect: (action, listenerApi) => {
      //  do job
    }
})

Then myAction action is defined in seprate MyAction-slice.ts as follows:

const applicationSlice = createSlice({
    name: 'app',
    initialState: initialState,
    reducers: {
        myAction(state) {
            // do pure functional code here
        },
    }
})

And it works fine when I call myAction from a React component (first myAction did its job, then createListenerMiddleware for that particular action has been fired, e.g:

return (
    <>
        <button onClick={() => dispatch(myAction())}>
    </>
)

However I also have a createAsyncThunk defined in MyAction-slice.ts as follows:

export const myAsyncAction = createAsyncThunk(
    'app/async',
    async () => {
        const promiseData = await axios.get(`https://localhost:8888/hello`)
        // handle errors for promiseData
        return promiseData
    }
)

And then I declare that thunk inside createSlice as follows:

...
extraReducers: (builder) => {
     builder
        .addCase(myAsyncAction.fulfilled, (state, payload) => {
            // change state with a pure functional way
        })
...

And also at the end of my MyAction-slice.ts file I export actions as:

export const {myAction} = applicationSlice.actions

My problem is that I wish to somehow "hook" to myAsyncAction.fulfilled reducer using createListenerMiddleware, the same way I did for myAction reducer. Is it even possible?

Upvotes: 1

Views: 320

Answers (1)

ojacomarket
ojacomarket

Reputation: 613

Your myAsyncAction.fulfilled is also an ActionCreator.

Add that to your MyAction-slice.ts after createAsyncThunk:

export const myAsyncActionCreator = myAsyncAction.fulfilled as AsyncThunkFulfilledActionCreator<AxiosResponse<any, any>, AsyncThunkConfig>

Also replace myAsyncAction.fulfilled to myAsyncActionCreator in your extraReducers.

Then your createListenerMiddleware would look like (store.ts):

export const listenerMiddleware = createListenerMiddleware()

listenerMiddleware.startListening({
    actionCreator: myAsyncActionCreator,
    effect: (action, listenerApi) => {
      //  do job
    }
})

Also don't forget to prepend this listener to your configureStore right after your reducers list:

export const store = configureStore({
reducer: {...}
middleware: (getDefaultMiddleware) =>
  getDefaultMiddleware().prepend(listenerMiddleware.middleware),
})

Following same idea, you could also create myAsyncAction.rejected action creator and export it in a same manner and use as:

listenerMiddleware.startListening({
  actionCreator: myAsyncActionCreatorRejected

Upvotes: 3

Related Questions