Using ‘history’ to navigate your React app from outside a component

Brandon Cantello
3 min readJun 6, 2020

If you have done any programming in React, you are probably familiar with basic routing using <Switch>, <Route>, and <Link>. To do this, we import BrowserRouter, HashRouter, MemoryRouter, or NativeRouter from react-router-dom and then wrap our <App /> component in our chosen router within index.js. This would look something like this:

import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter} from "react-router";
import App from './App';

ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);

Now we have the freedom to use the aforementioned tags anywhere within our application. However, what you may not know is that whenever we use any of the above listed routers, React creates a history object for us to use as well and passes that object within the default props. For example, assume no props have been passed to the Login component. Login can still accept the default props and utilize the history object in this way:

import React from 'react';export default function Login(props) {
props.history.push('/home')
}

We would obviously want some additional logic in there, but the point is that we can access the history object through props, even though no props were passed to Login, and use history.push to push a new entry onto the history stack. Based on the above example, this will route the user to the component associated with the /home url. Well that was easy!

But what happens if we actually pass props to Login, thus overwriting the default props containing the history object? Or what about trying to access the history object from outside of a component?

Spoiler…the above approach won’t work! In this case, we need to create our own history object, in its own module, and import it where it is needed in our application.

Note: If you are attempting to use history inside of a component and are using React version 16.8 or later, there is an easier way to accomplish this. See my article Navigating your React app with the useHistory hook instead.

First, we need to create the history module. Create a new JavaScript file called history.js. Then add the following code to the file:

import {createBrowserHistory} from 'history';
export default createBrowserHistory();

Next, we need to update index.js to use the generic <Router> instead of one of the fancy routers that we listed at the beginning of this article. We will also need to import history.js like so:

import React from 'react';
import ReactDOM from 'react-dom';
import {Router} from "react-router";
import App from './App';
import history from "./history";

ReactDOM.render(
<Router history={history}>
<App />
</Router>,
document.getElementById('root')
);

Now we can utilize history whether or not we are inside a component, and regardless of props, by just importing history wherever it is needed! For example:

import React from 'react';
import history from "./history";
export default function Login() {
history.push('/home')
}

There are a number of other properties that are usually included within the history object. In this example we used history.push, but you could also use:

  • length - (number) The number of entries in the history stack
  • action - (string) The current action (PUSH, REPLACE, or POP)
  • push(path, [state]) - (function) Pushes a new entry onto the history stack
  • replace(path, [state]) - (function) Replaces the current entry on the history stack
  • go(n) - (function) Moves the pointer in the history stack by n entries
  • goBack() - (function) Equivalent to go(-1)
  • goForward() - (function) Equivalent to go(1)
  • block(prompt) - (function) Prevents navigation

This list is not exhaustive, so I encourage you to dig a little deeper into history on your own!

Has using history gotten you out of a bind in the past? Do you think it just might solve a problem you are facing now? I’d love to hear about it!

--

--

Brandon Cantello

I’m a software engineer based in Santa Barbara CA. I enjoy building user centric applications and websites that are as intuitive as they are dynamic.