Search code examples
reactjsreduxmiddlewareredux-toolkit

Redux Toolkit addListener typescript error in component (createListenerMiddleware)


I am following the Redux Toolkit's documentation to add a listener in my component as such:

import { useDispatch } from 'react-redux'

...
const dispatch = useDispatch()
useEffect(() => {
    return dispatch(
      addAppListener({
        matcher: isAnyOf(
          updateResponse,
          ...
        ),
        effect: async (action, listenerApi) => {
           ...
        }
      })
    )
  }, [])

I've also typed the app listener like it recommends in the documentation. Here is how I did it for reference:

import { addListener, createListenerMiddleware } from '@reduxjs/toolkit'
import type { TypedAddListener, TypedStartListening } from '@reduxjs/toolkit'
import type { AppDispatch, RootState } from './store'

export const listenerMiddleware = createListenerMiddleware()

export type AppStartListening = TypedStartListening<RootState, AppDispatch>

export const startAppListening =
  listenerMiddleware.startListening as AppStartListening

export const addAppListener = addListener as TypedAddListener<
  RootState,
  AppDispatch
>

However, my useEffect return in my component is getting the following error:

Argument of type '() => { payload: ListenerEntry<EmptyObject & { user: WritableDraft<UserState>; authentication: AuthenticationState; }, ((action: Action<...>) => UnsubscribeListener) & ... 1 more ... & Dispatch<...>>; type: "listenerMiddleware/add"; }' is not assignable to parameter of type 'EffectCallback'.
  Type '{ payload: ListenerEntry<EmptyObject & { user: WritableDraft<UserState>; authentication: AuthenticationState; }, ((action: Action<...>) => UnsubscribeListener) & ... 1 more ... & Dispatch<...>>; type: "listenerMiddleware/add"; }' is not assignable to type 'void | Destructor'.

Any idea what's causing this?


Solution

  • It looks like you aren't using a correctly typed version of useDispatch in that component. It's still just using the basic Redux built-in Dispatch type, which doesn't know that you've got the listener middleware set up.

    You need to follow our directions for setting up a pre-typed version of useDispatch based on your store's configuration, and use that pre-typed hook in this component: