22

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!

2
  • 2
    hey, I have the same problem. did you find any solution? Commented Nov 17, 2021 at 7:41
  • @pedramafra Yes, I just wrote the answer Commented Nov 17, 2021 at 10:42

4 Answers 4

23

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.

Sign up to request clarification or add additional context in comments.

2 Comments

a good way to reach this
great, all i had to do was move browserrouter higher up! thanks
11

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")

Comments

0

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} />

3 Comments

I am not quite sure if this is good solution. The react-router team explicitly move from history to navigate with the goal of "better compatibility with React suspense" reactrouter.com/docs/en/v6/upgrading/…
@bukso As I wrote in the edit, they added it themselves to the library in 6.1
Kadlek, okay, but it is still unstable - github.com/remix-run/react-router/releases
0

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.