Negin
Negin

Reputation: 331

How to make a wrapper function for Navigate in react router v6

I'm using react-router v5 and I want to upgrade to v6. There is a problem: I have many components and use useHistory inside them but I don't want to change them one by one to useNavigate instead of that I want to write a helper function for navigate(history) in react-router v6 and then use that helper(wrapper) function.

Question is: How to write a helper function for useNavigate in react-router v6?

Upvotes: 3

Views: 1543

Answers (1)

Drew Reese
Drew Reese

Reputation: 202846

If you are wanting to provide a custom navigation utility then you'll likely want to create a custom React hook that "wraps" one of the hooks provided from react-router and return the functions you need. Unfortunately react-router@6 doesn't directly expose out the history object, and there isn't a 1-to-1 relationship between the history object and the navigate function. You can cover most common use cases though. I suggest adhering to a "common API" that fits your needs.

RRDv5 Example

import { useHistory } from 'react-router';

const useMyNavigation = () => {
  const history = useHistory();

  const push = React.useCallback((to, state) => history.push(to, state), []);

  const replace = React.useCallback((to, state) => history.replace(to, state), []);

  const go = React.useCallback((delta) => history.go(delta), []);

  const back = React.useCallback(() => history.back(-1), []);

  const forward = React.useCallback(() => history.go(1), []);

  return {
    back
    forward,
    go,
    push,
    replace
  };
};

RRDv6 Example

import { useNavigate } from 'react-router';

const useMyNavigation = () => {
  const navigate = useNavigate();

  const push = React.useCallback((to, state) => navigate(to, { state }), []);

  const replace = React.useCallback((to, state) => navigate(to, { replace: true, state }), []);

  const go = React.useCallback((delta) => navigate(delta), []);

  const back = React.useCallback(() => navigate(-1), []);

  const forward = React.useCallback(() => navigate(1), []);

  return {
    back
    forward,
    go,
    push,
    replace
  };
};

Alternative RRDv6 Example

Now, when I said that RRDv6 doesn't directly expose out the history object, this isn't entirely true. It does not directly export the history object, but it does export the React context holding it via the UNSAFE_NavigationContext context. With this you can get a reference to the navigator function which is a history@5 history object (as opposed to the history@4 that RRDv5 uses). Note that this likely requires history@5 (the same version used by react-router@6) to be listed as a project dependency. See history@5 Navigation.

import { useContext } from 'react';
import { useNavigate } from 'react-router';

const useMyNavigation = () => {
  const navigator = useContext(UNSAFE_NavigationContext).navigator;

  const push = React.useCallback((to, state) => navigator.push(to, state), []);

  const replace = React.useCallback((to, state) => navigator.replace(to, state), []);

  const go = React.useCallback((delta) => navigator.go(delta), []);

  const back = React.useCallback(() => navigator.back(-1), []);

  const forward = React.useCallback(() => navigator.go(1), []);

  return {
    back
    forward,
    go,
    push,
    replace
  };
};

Upvotes: 1

Related Questions