Search code examples
reduxnext.jsserver-side-renderingredux-toolkit

next-redux-wrapper: after hydration useSelector returns initial value (null), but getServerSideProps passes the correct value to the page


I got getServerSideProps like this, which gets token from cookie and gets uses it to fetch user data with RTKQ endpoint. Then dispatches that data to authSlice. So far it's good.


const getServerSideProps = wrapper.getServerSideProps(
  (store) =>
    async ({ req, res }: GetServerSidePropsContext) => {
      let result: AuthState = null;

      const data = getCookie('device_access_token', { req, res });

      if (data?.toString()) {
        result = await store
          .dispatch(
            usersApi.endpoints.getUserByToken.initiate(data?.toString())
          )
          .unwrap();
      }
      if (result) store.dispatch(setUser(result));

      return { props: { auth: result } };
    }
);

Then I merge this auth data in the store like this:

const reducer = (state: ReturnType<typeof rootReducer>, action: AnyAction) => {
  if (action.type === HYDRATE) {
    console.log('payload@HYDRATE', action.payload);

    const nextState = {
      ...state, // use previous state
      ...action.payload, // apply delta from hydration
    };
    if (state.auth.user) {
      nextState.auth.user = state.auth.user;
      nextState.auth.token = state.auth.token;
    } // preserve auth value on client side navigation

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

console.log('payload@HYDRATE', action.payload); also shows correct data.

The problem is in a page where I export getServerSideProps,

const IndexPage: NextPage = ({ auth }: any) => {
  console.log('user@index', auth);
  console.log('userSelect@index', useSelector(selectCurrentUser));

  return auth ? <Home /> : <NoAuthHome />;
};

auth shows correct value, but useSelector(selectCurrentUser) shows null

Can someone tell me if this is how it is intended to be, or I'm doing something wrong?

Because I don't want prop-drilling auth on countless pages, just use useSelector(selectCurrentUser) wherever necessary.


Solution

  • Finally found the problem!

    problem was in _app.tsx I wrapped <Component {...pageProps} /> with <Provider store={store} at the same time exporting with wrapper.withRedux(MyApp)