You are using legacy implementaion. Please update your code: use createWrapper() and wrapper.useWrappedStore(). nextjs redux?
Asked Answered
S

2

15

I am facing error with using redux toolkit with next js. I facing this lagacy warning-

/!\ You are using legacy implementaion. Please update your code: use createWrapper() and wrapper.useWrappedStore().

I am not understanding where actually problem occurred and I have to update my code.

Here is code-

this is store.ts-

import { Action, configureStore, ThunkAction } from "@reduxjs/toolkit";
import { createWrapper, HYDRATE } from "next-redux-wrapper";
import { combinedReducer } from "./Reducer";

const reducer: typeof combinedReducer = (state, action) => {
    if (action.type === HYDRATE) {
        const nextState = {
            ...state,
            ...action.payload,
        };
        return nextState;
    } else {
        return combinedReducer(state, action);
    }
};

export const makeStore = () => configureStore({ reducer });

type Store = ReturnType<typeof makeStore>;

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(makeStore);

Here is reducer.ts-

import { combineReducers } from '@reduxjs/toolkit';

export const combinedReducer = combineReducers({
    //All reducer
});

Here is Hook.ts-

import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import type { RootState, AppDispatch } from './Store';

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

And last here is app.tsx-

function MyApp(props: MyAppProps) {
  const { Component, emotionCache = clientSideEmotionCache, pageProps } = props;
  return (
    <CacheProvider value={emotionCache}>
      <Head>
        <meta name="viewport" content="initial-scale=1, width=device-width" />
      </Head>
      <ThemeProvider theme={theme}>
        <CssBaseline />
        <NextProgress
          delay={2000}
          options={{ showSpinner: false }}
          color="#eb5525"
        />
        <Component {...pageProps} />
      </ThemeProvider>
    </CacheProvider>
  );
}
export default wrapper.withRedux(MyApp);

*** With the same code I do not get any warning. But when I update my projects to latest package then I am getting the error.

Please help me actually where I have to update my code according to warning?

Sunbeam answered 18/9, 2022 at 8:39 Comment(0)
E
30

The warning comes from this line. So the warning will come up whenever someone uses wrapper.withRedux method (the old way).

To fix this, we have to use useWrappedStore to create a store, and use react-redux's Provider to pass the store down to the children:

import { FC } from "react";
import { Provider } from "react-redux";
import type { AppProps } from "next/app";
import { wrapper } from "../app/store";

const MyApp: FC<AppProps> = ({ Component, ...rest }) => {
  const { store, props } = wrapper.useWrappedStore(rest);
  const { emotionCache = clientSideEmotionCache, pageProps } = props;
  return (
    <Provider store={store}>
      <CacheProvider value={emotionCache}>
        ...
        <Component {...pageProps} />
        ...
      </CacheProvider>
    </Provider>
  );
};

export default MyApp;
Eightfold answered 27/9, 2022 at 1:48 Comment(0)
A
2

It seems they haven't fully updated their documentation on this. Going by this code example this is what your MyApp would have to look like:

function MyApp(props: MyAppProps) {
  const { Component, ...rest } = props
  const { emotionCache = clientSideEmotionCache, pageProps } = wrapper.useWrappedStore(rest);
  return (
   <Provider store={store}>
    <CacheProvider value={emotionCache}>
      // ...
    </CacheProvider>
   </Provider>
  );
}
export default MyApp;
Allocation answered 18/9, 2022 at 9:8 Comment(5)
Can you say me one more things? Every thing in store.ts, reducer.ts and hook.ts I write is okay and production ready?Sunbeam
Actually I am little bit closer call confused.Sunbeam
You really just change what is shown here: use wrapper.useWrappedStore(rest), add the <Provider store={store}> and remove the withWrapper from the export default. The rest of your code is okay.Allocation
The (big) problem with this suggested approach is that you can not use the store in the MyApp since your sore becomes available only in the child components. Using store in MyApp can be helpful when you want to do something client side on every page. I just ignore this deprecation warning. It does not hurt in any way :)Graduated
Then you can still just wrap your MyApp in another component. It has always been the case in React applications that the top-level component of your app had no access to the Redux store since it had to render the Provider itself. All that the old solution did was create an artificial top-level component around your MyApp. Honestly, I wouldn't keep using a deprecated feature. It will be removed at some point. What I showed above is the official way of doing it now.Allocation

© 2022 - 2024 — McMap. All rights reserved.