Reputation: 1376
Right now I have an History module, that let me use the history even outside of react component:
import { createBrowserHistory } from 'history';
export default createBrowserHistory();
Then I use this history in App.jsx directly
import { Router } from 'react-router-dom';
...
<Router history={history}>...</Router>
I can import and use the same history object everywhere. Even in custom helpers outside of any react components.
How could this work in react router 6?
Since history is replaced with navigate, I don't see any solution yet online.
I know it is still beta, but I would like to check on it in advance.
Thanks for any ideas!
Upvotes: 22
Views: 10496
Reputation: 1008
Inspired by @bukso, I ended up with the following solution in TypeScript.
global-history.tsx
import { useNavigate, NavigateFunction } from "react-router-dom";
export let globalNavigate: NavigateFunction;
export const GlobalHistory = () => {
globalNavigate = useNavigate();
return null;
};
index.tsx
<React.StrictMode>
<BrowserRouter>
<GlobalHistory />
{/* ... */}
</BrowserRouter>
</React.StrictMode>
Now, you're ready to use it outside React components. globalNavigate("profile")
Upvotes: 11
Reputation: 1485
Here is my solution, I wanted to navigate from the navbar back to the home page.
Create a HistoryRouter
component & wrap your navbar or similar & then create react browser router separately for your routes.
import {createBrowserRouter, Link, unstable_HistoryRouter as HistoryRouter} from "react-router-dom";
export const history = createBrowserHistory({ window });
const App = () => {
return (
<>
<HistoryRouter history={history}>
<Navbar />
</HistoryRouter>
<RouterProvider router={router} />
</>
);
}
Then create a function that uses the history object to push the new path in the window's location.
import {history} from "../app";
export const logout = (to: string): void => {
// e.g removeToken();
history.push(to);
window.location.reload();
};
I can now use the logout
function in my navbar, for example:
<nav>
<button onClick={_ => logout("/")}>Logout</button>
</nav>
Upvotes: 0
Reputation: 4975
In my case I needed access to the history object before first render, so I ended up writing custom component around Router
based on the BrowserRouter
implementation that would allow me to pass in history through props.
See https://github.com/remix-run/react-router/discussions/8241#discussioncomment-1677474 for code.
Edit: As of react-router-dom v6.1.0 HistoryRouter is part of its implementation so you can just directly do:
import {unstable_HistoryRouter as HistoryRouter} from 'react-router-dom'
import {createBrowserHistory} from 'history'
const history = createBrowserHistory()
<HistoryRouter history={history} />
Upvotes: 0
Reputation: 1376
I ended up with following solutions:
At first, react-router-dom 6 has navigate and not history. It is better to use navigate for the navigation trough the routes:
I create and fix my History object, so that it can continue work with 'push' and that I don't need big rework:
const History = {
navigate: null,
push: (page, ...rest) => History.navigate(page, ...rest),
};
export default History;
Then I made my own Component that set the navigation:
import { useNavigate } from 'react-router-dom';
const NavigateSetter = () => {
History.navigate = useNavigate();
return null;
};
Then while defining the default router, I place as a child the setter:
import { BrowserRouter } from 'react-router-dom';
<BrowserRouter>
<NavigateSetter />
<App />
</BrowserRouter>
After that you can use everywhere History.push or History.navigate with the default react-router-dom's navigate API.
Upvotes: 23