next-redux-wrapper icon indicating copy to clipboard operation
next-redux-wrapper copied to clipboard

typescript error in configureStore

Open deeeed opened this issue 2 years ago • 2 comments

Typescript unhappy with the type but not sure how to adjust it.

Here is my code:

const allReducers = {
  App: appReducer,
  ThemeSwitcher: themeSwitcherReducer,
  Auth: authReducer,
  [articleApi.reducerPath]: articleApi.reducer,
};
const combinedReducer = combineReducers(allReducers);

const reducer = (state: ReturnType<typeof combinedReducer>, action: AnyAction) => {
  console.log(`reducer action ${action.type}`, action);
  if (action.type === HYDRATE) {
    const nextState = {
      ...state, // use previous state
      ...action.payload, // apply delta from hydration
    };
    return nextState;
  } else {
    return combinedReducer(state, action);
  }
};

export const store = configureStore({
  reducer: reducer,
  middleware: getDefaultMiddleware => {
    return getDefaultMiddleware().concat(articleApi.middleware);
  },
});

export const initStore = () => {
  return store;
};

type Store = ReturnType<typeof initStore>;

export type AppDispatch = Store['dispatch'];
export type RootState = ReturnType<Store['getState']>;
export type AppThunk<ReturnType = void> = ThunkAction<ReturnType, RootState, unknown, Action<string>>;

export const wrapper = createWrapper(initStore, { debug: process.env.NODE_ENV === 'development' });

The error is on configureStore param reducer: reducer:

Type '(state: ReturnType<typeof combinedReducer>, action: AnyAction) => any' is not assignable to type 'Reducer<CombinedState<{ App: AppState; ThemeSwitcher: { isActivated: boolean; changeThemes: IThemeElementOptions; topbarTheme: IThemeElementOptions; sidebarTheme: IThemeElementOptions; layoutTheme: IThemeElementOptions; }; Auth: Auth; articleApi: CombinedState<...>; }>, AnyAction> | ReducersMapObject<...>'.
  Type '(state: ReturnType<typeof combinedReducer>, action: AnyAction) => any' is not assignable to type 'Reducer<CombinedState<{ App: AppState; ThemeSwitcher: { isActivated: boolean; changeThemes: IThemeElementOptions; topbarTheme: IThemeElementOptions; sidebarTheme: IThemeElementOptions; layoutTheme: IThemeElementOptions; }; Auth: Auth; articleApi: CombinedState<...>; }>, AnyAction>'.
    Types of parameters 'state' and 'state' are incompatible.
      Type 'CombinedState<{ App: AppState; ThemeSwitcher: { isActivated: boolean; changeThemes: IThemeElementOptions; topbarTheme: IThemeElementOptions; sidebarTheme: IThemeElementOptions; layoutTheme: IThemeElementOptions; }; Auth: Auth; articleApi: CombinedState<...>; }> | undefined' is not assignable to type 'CombinedState<{ App: AppState; ThemeSwitcher: { isActivated: boolean; changeThemes: IThemeElementOptions; topbarTheme: IThemeElementOptions; sidebarTheme: IThemeElementOptions; layoutTheme: IThemeElementOptions; }; Auth: Auth; articleApi: CombinedState<...>; }>'.
        Type 'undefined' is not assignable to type 'CombinedState<{ App: AppState; ThemeSwitcher: { isActivated: boolean; changeThemes: IThemeElementOptions; topbarTheme: IThemeElementOptions; sidebarTheme: IThemeElementOptions; layoutTheme: IThemeElementOptions; }; Auth: Auth; articleApi: CombinedState<...>; }>'.
          Type 'undefined' is not assignable to type 'EmptyObject'.

I probably just need casting but I am not sure of the correct type... Any help much appreciated :)

deeeed avatar Dec 31 '21 08:12 deeeed

Looks like you shouldn't use the combinedReducer

Maybe something like this:

export const store = configureStore({
  reducer: {
    App: appReducer,
    ThemeSwitcher: themeSwitcherReducer,
    Auth: authReducer,
    [articleApi.reducerPath]: articleApi.reducer,
  },
});

export const initStore = () => {
  return store;
};

type Store = ReturnType<typeof initStore>;

export type AppDispatch = Store['dispatch'];
export type RootState = ReturnType<Store['getState']>;
export type AppThunk<ReturnType> = ThunkAction<
  ReturnType,
  RootState,
  unknown,
  Action<string>
>;

export const wrapper = createWrapper(initStore, {
  debug: process.env.NODE_ENV === 'development',
});

VictorKolb avatar Mar 01 '22 13:03 VictorKolb

I tried got solution about this problem but I don't found nothing really good. For hour I use this hack (this is shit, but works.).

import { rootReducer } from './modules/root';

const combinedReducer = combineReducers(rootReducer);

const reducer = (
  state: ReturnType<typeof combinedReducer>,
  action: AnyAction,
) => {
  if (action.type === HYDRATE) {
    const nextState = {
      ...state, // use previous state
      ...action.payload, // apply delta from hydration
    };

    return nextState;
  } else {
    return combinedReducer(state, action);
  }
};

const makeStore = () =>
  configureStore({
    reducer: reducer as typeof combinedReducer,
  });

type Store = ReturnType<typeof makeStore>;

export type RootState = ReturnType<Store['getState']>;
export type AppThunk<ReturnType = void> = ThunkAction<
  ReturnType,
  RootState,
  unknown,
  Action<string>
>;

export type AppDispatch = Store['dispatch'];
export const useAppDispatch: () => AppDispatch = useDispatch;

export const wrapper = createWrapper<Store>(makeStore, {
  debug: process.env.NODE_ENV !== 'production',
});

If I found a better solution of that, I return here.

mnzsss avatar Nov 15 '22 20:11 mnzsss