Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get history and match in this.props in nextjs?

I want to get values of history and match in this.props. I am using next/router to import withRouter. I wanted to use this.props.match.params to get values in the url and history.push to redirect. How can get this in Next.js. Right now I am not getting history and match in this.props.

like image 870
Logeswari Avatar asked Dec 10 '22 02:12

Logeswari


2 Answers

EDIT: I had to turn back to the global Router. The useRouter hook does not work, since its life cycle seems to be different and thus I cannot grab the exact values that I need at the given times.

.....
    if (
      !shallow &&
      !(EXCEPTIONS.includes(nextUrl) || EXCEPTIONS.includes(Router.asPath)) &&
      nextUrl !== Router.asPath
    ) {
      setPreviousRoute(Router.asPath);
    }
  };

  useEffect(() => {
    Router.events.on('beforeHistoryChange', handleBeforeHistoryChange);

    return () => {
      Router.events.off('beforeHistoryChange', handleBeforeHistoryChange);
    };
  }, []);

  return { previousRoute };
};

EDIT: Since the global Router object pollution is not a nice thing to do, you could use a state variable instead:

const EXCEPTIONS = ['/sign-up'];

/**
 * Saves the current URL before changing the route.
 */
const useRouteUrlHistory = () => {
  const [previousRoute, setPreviousRouter] = useState('');
  const router = useRouter();

  const handleBeforeHistoryChange = (url) => {
    const [nextUrl] = url?.split('?') || [];

    if (
      !(EXCEPTIONS.includes(nextUrl) || EXCEPTIONS.includes(router.asPath)) &&
      nextUrl !== router.asPath
    ) {
      setPreviousRouter(router.asPath);
    }
  };

  useEffect(() => {
    router.events.on('beforeHistoryChange', handleBeforeHistoryChange);

    return () => {
      router.events.off('beforeHistoryChange', handleBeforeHistoryChange);
    };
  }, []);

  return { previousRoute };
};

export default useRouteUrlHistory;

You have to use the hook in your _app.js since you listen for route changes and want to save/access the previousRoute globally.

const MyApp = ({ Component, pageProps }) => {

  const { previousRoute } = useRouteUrlHistory();

  return (
        <ApplicationContext.Provider
          value={{
            previousRoute,
            ... another global context
          }}
        >
           ... components etc.
        </ApplicationContext.Provider>

=====

I have not found an elegant way to be able to access Router.history in its entirety. But often enough I wanted to access at least the last visited route, which forced me to this workaround. It might not be the most elegant way since it pollutes the global Router object, but as I said I have not found any alternative.

I only check for the actual route which was visited previously. You may also implement your logic to check the params. The hook plugs-in before the Router handles the actual Route change. Which allows you to listen to the Router.previousRoute property within you application.

KEEP IN MIND if you do shallow Routing you may not affect the Router.history, which will probably not trigger this event hook.

const EXCEPTIONS = ['/sign-up'];

/**
 * Saves the current URL before changing the route.
 * The previousRoute is then accessible via the global Router.
 */
const useRouteUrlHistory = () => {
  const handleBeforeHistoryChange = (url) => {
    const [nextUrl] = url?.split('?') || [];

    if (
      !(EXCEPTIONS.includes(nextUrl) || EXCEPTIONS.includes(Router.asPath)) &&
      nextUrl !== Router.asPath
    ) {
      Router.previousRoute = Router.asPath;
    }
  };

  useEffect(() => {
    Router.events.on('beforeHistoryChange', handleBeforeHistoryChange);

    return () => {
      Router.events.off('beforeHistoryChange', handleBeforeHistoryChange);
    };
  }, []);
};

export default useRouteUrlHistory;
like image 103
dimisus Avatar answered Jan 21 '23 09:01

dimisus


next/router doesn't provide you history as react-dom-router does, it gives you something called query in your component's props.

This is the official usage example.

import { useRouter } from 'next/router'

const Post = () => {
  const router = useRouter()
  const { pid } = router.query

  return <p>Post: {pid}</p>
}

export default Post

If you want to push routes, you can follow this one. example.

import Router from 'next/router'

function ReadMore() {
  return (
    <div>
      Click <span onClick={() => Router.push('/about')}>here</span> to read more
    </div>
  )
}

export default ReadMore
like image 21
Sultan H. Avatar answered Jan 21 '23 11:01

Sultan H.