I've been looking for this question and found it but they're using class components and react router dom v5
What i want is When user click browser back button I'll redirect them to home page
Well after a long journey to find out how to do that finally i came up with this solution
window.onpopstate = () => {
navigate("/");
}
If you are simply wanting to run a function when a back navigation (POP action) occurs then a possible solution is to create a custom hook for it using the exported NavigationContext.
Example:
import { UNSAFE_NavigationContext } from "react-router-dom";
const useBackListener = (callback) => {
const navigator = useContext(UNSAFE_NavigationContext).navigator;
useEffect(() => {
const listener = ({ location, action }) => {
console.log("listener", { location, action });
if (action === "POP") {
callback({ location, action });
}
};
const unlisten = navigator.listen(listener);
return unlisten;
}, [callback, navigator]);
};
Usage:
import { useNavigate } from 'react-router-dom';
import { useBackListener } from '../path/to/useBackListener';
...
const navigate = useNavigate();
useBackListener(({ location }) => {
console.log("Navigated Back", { location });
navigate("/", { replace: true });
});
If using the UNSAFE_NavigationContext context is something you'd prefer to avoid then the alternative is to create a custom route that can use a custom history object (i.e. from createBrowserHistory) and use the normal history.listen. See my answer here for details.
import { useEffect, useContext } from "react";
import { NavigationType, UNSAFE_NavigationContext } from "react-router-dom";
import { History, Update } from "history";
const useBackListener = (callback: (...args: any) => void) => {
const navigator = useContext(UNSAFE_NavigationContext).navigator as History;
useEffect(() => {
const listener = ({ location, action }: Update) => {
console.log("listener", { location, action });
if (action === NavigationType.Pop) {
callback({ location, action });
}
};
const unlisten = navigator.listen(listener);
return unlisten;
}, [callback, navigator]);
};
You can also use the useNavigationType hook if all you want is to know if a POP action occurred.
import {
useLocation,
useNavigationType,
NavigationType
} from "react-router-dom";
const useBackListener = (callback) => {
// Ref is used to handle any React.StrictMode double-mounting
const initialRender = React.useRef(true);
const location = useLocation();
const navigationType = useNavigationType();
useEffect(() => {
if (!initialRender.current && navigationType === NavigationType.Pop) {
initialRender.current = false;
callback({ location });
}
}, [callback, location, navigationType]);
};
With the Data routers you can use the (currently still used) router.subscribe handler to replace history.listen. It is easily also abstracted into a custom if necessary. Note that subscribe is not currently part of the "public" API and exists similar to NavigationContext and HistoryRouter where they could be removed at any time. See this Github issue for more details/explanation.
Example:
const router = createBrowserRouter([
...
]);
export default function App() {
React.useEffect(() => {
router.subscribe((state) => {
if (state.historyAction === NavigationType.Pop) {
....
}
});
}, []);
return <RouterProvider router={router} />;
}
Example state value:
{
actionData: null,
blockers: {size: 0},
errors: null,
fetchers: {size: 0},
historyAction: "PUSH",
initialized: true,
loaderData: {},
location: {
pathname: '/1',
search: '',
hash: '',
state: null,
key: 'oy0tkdth'
},
matches: [{…}, {…}],
navigation: {
state: 'idle',
location: undefined,
formMethod: undefined,
formAction: undefined,
formEncType: undefined,
…
},
preventScrollReset: false,
restoreScrollPosition: null,
revalidation: "idle"
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With