reactjsreduxredux-toolkitredux-reducersconnected-react-router

Configure reducers of connected-react-router and Redux Toolkit Query properly


I am trying to setup reducers of both connected-react-router and RTK Query.
(The old code base has connected-react-router already)
Then I received this error.

fail to setup connectRouter

Type 'Reducer<RouterState<unknown>, AnyAction>' is not assignable to type 'Reducer<unknown, AnyAction>'.
Types of parameters 'state' and 'state' are incompatible.
Type 'unknown' is not assignable to type 'RouterState<unknown>'.

My "mockApi" is quite simple. "orderApi" is somewhat the same.

export const mockApi = createApi({
  reducerPath: "mockupPath",
  baseQuery: fetchBaseQuery({ baseUrl: "http://jsonplaceholder.typicode.com" }),
  endpoints: (builder) => ({
    getPost: builder.query<MockResonse, number>({
      query: (id) => `/posts/${id}`,
    }),
  }),
})
interface MockResonse { userId: number, id: number, title: string, body: string, }

While using combineReducers produces no type error,

reducer: combineReducers({
  router: connectRouter(history),
  [mockApi.reducerPath]: mockApi.reducer,
}),

but I lose the type of the store.
Knowing the type of the store is a huge advantage in development, so I'm trying to figure out how to solve the error.

May I know if I'm wrong somewhere?


Solution

  • This TypeScript error occurs when using connected-react-router with newer versions of history and react-router.

    The type for the connectRouter function looks like this:

    export function connectRouter<S = LocationState>(history: History<S>)
        : Reducer<RouterState<S>>
    

    (source)

    You can see that it is a generic function where the generic type parameter S refers to the type of the state that is stored in your history.

    If you have a new version of history (5.2+), then History<S> is now a TypeScript error because the History interface is no longer generic. This is a recent change which was released in history version 5.2.0.

    You can fix the error by explicitly setting the generic type parameter for the connectRouter function call to unknown:

    router: connectRouter<unknown>(history)
    
    const store = configureStore({
      reducer: {
        [mockApi.reducerPath]: mockApi.reducer,
        router: connectRouter<unknown>(history)
      }
    })
    

    The inferred type of the router reducer is now Reducer<RouterState<unknown>, AnyAction>.