Reputation: 331
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
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.
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
};
};
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
};
};
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