kirill-konshin / next-redux-wrapper

Redux wrapper for Next.js

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

GSSP ajax-mode -- HYDRATE-action not dispatching

chiralium opened this issue · comments

Describe the bug

When use navigate the page by shallow routing and use back/forward browser button, library not call HYDRATE-action and url is change but state is not.

To Reproduce

  1. Create page that containing for example pagination
  2. The page number changed by url-parameter ?page via:
await Router.push({
  query: {
    ...Router.query,
    page: newPage,
  }
}, undefined, {shallow: true});
  1. Click on pagination button is ok, but click to native back/forward-button in browser have no effect: the GSSP-function is called by Next.Js (ajax-request is sent) but redux state not changed at all.

Expected behavior

Library change the state via back/fowrad history transtion

Additional context

I fix the issue by adding custom hook:

import { useRouter } from 'next/router';
import { HYDRATE } from 'next-redux-wrapper';
import { useCallback, useEffect, useState } from 'react';
import { useAppDispatch } from 'src/redux/hooks/useAppDispatch';
import { TAppRootState } from 'src/redux/types';

export const useHistoryHydration = (state: TAppRootState) => {
  const router = useRouter();
  const dispatch = useAppDispatch();
  const [isHistoryTransition, setIsHistoryTransition] = useState<boolean>(false);

  const handleHistoryChange = useCallback(() => {
    if (!isHistoryTransition) {
      return true;
    }

    dispatch({
      payload: state,
      type: HYDRATE,
    });

    setIsHistoryTransition(false);

    return true;
  }, [dispatch, isHistoryTransition, state]);

  useEffect(() => {
    router.events.on('routeChangeComplete', handleHistoryChange);

    // eslint-disable-next-line consistent-return
    return () => router.events.off('routeChangeComplete', handleHistoryChange);
  }, [handleHistoryChange, isHistoryTransition, router.events, router.isReady]);

  useEffect(() => {
    router.beforePopState(({ url, as, options }) => {
      if (options.shallow) {
        router.replace(url, as, { ...options, shallow: false });
        return false;
      }

      setIsHistoryTransition(true);

      return true;
    });
  }, [router]);
};

and using it like this:

export type TNextPageProps = {
  store: TAppStore;
};

const Catalog: React.FC<TNextPageProps> = ({ store }) => {
  useHistoryHydration(store.getState());
  // ...