store.getState() is empty on server-side. "next-redux-wrapper"/"redux-toolkit"

74 Views Asked by At

Ok, hi everyone. I require assistance realy bad. I`m trying to implement "next-redux-wrapper" into my portfolio project. Result i wanna reach:

const PortfolioRoute = ({ status }) => {

  if (status !== 200) return <ErrorPage statusCode={status} />

  const { portfolio } = useSelector((state: RootState) => state.pagePortfolio)

  return portfolio.length ? <PagePortfolio /> : null
}

export const getServerSideProps = wrapper.getServerSideProps(
  (store) => async () => {
    const currentState = store.getState()
    if (currentState.pagePortfolio.portfolio.length) {
      return {
        props: {
          status: 200,
        },
      }
    } else {
      const response = await REQUEST.getPortfolio()
      store.dispatch(initPortfolio(response.data))
      return {
        props: {
          status: response.status,
        },
      }
    }
  }
)

export default withCart(PortfolioRoute)

Basically, i wanna read my redux-toolkit store before the page loads. If my projects already loaded from other page - just grab them via useSelector, otherwise - fetch them and write in store. Code that fetches projects on other page:

  const dispatch = useDispatch()

  const { portfolio } = useSelector((state: RootState) => state.pagePortfolio)

  React.useEffect(() => {
    if (!portfolio.length) {
      REQUEST.getPortfolio().then((res) => {
        if (res.status === 200) {
          dispatch(initPortfolio(res.data))
        }
      })
    }
  }, [])

This is what i wrote in my store.tsx component:

const combinedReducer = combineReducers({
  pageInteriorIdeas: pageIdeasReducer,
  pagePortfolio: pagePortfolioReducer,
})

const reducer = (
  state: ReturnType<typeof combinedReducer>,
  action: AnyAction
) => {
  if (action.type === HYDRATE) {
    const nextState = {
      ...state,
      ...action.payload,
    }
    nextState.pagePortfolio = state.pagePortfolio
    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, { debug: true })

My app.tsx:

const MyApp = ({ Component, ...rest }) => {
    
    const {store, props} = wrapper.useWrappedStore(rest)

    return (
        <Provider store={store}>
            <Layout layoutData={layoutData.data}>
                <Component {...props.pageProps} />
            </Layout>
        </Provider>
    )
}

This is how i want to test a result, after route on this page with loaded data:

const PortfolioRoute = (props) => {

  console.log(
    "server_side_portfolio",
    JSON.parse(props.state).pagePortfolio.portfolio
  )

  const { portfolio } = useSelector((state: RootState) => state.pagePortfolio)

  console.log("client_stored_portfolio", portfolio)

  return null
}

export const getServerSideProps = wrapper.getServerSideProps(
  (store) => async () => {
    const currentState = store.getState()
    return {
      props: {
        state: JSON.stringify(currentState),
      },
    }
  }
)

export default withCart(PortfolioRoute)

Result: store empty on server and loaded on client

I`m realy nead advice. I spent the whole day searching for possible solutions - to no avail.

I`m realy nead advice. I spent the whole day searching for possible solutions - to no avail.

0

There are 0 best solutions below