Programmatic access to history (history.push etc) in react-router v5 outside of components

Asked
Active3 hr before
Viewed126 times

9 Answers

outsiderouterhistoryreactaccess
90%

Thanks, so using import { Router } from 'react-router-dom'; instead BrowserRouter helped! Also, you need to import your history and pass as a prop to Router: <Router history={history}>,Edit: My bad, I was using Router before not BrowserRouter which is needed for SSR. BrowserRouter might have never given this option. So it seems like the only solution is to split up the entry component and get history from useHistory hook and then pass it to ApolloClient or whatever.,And then use the exposed history in this file in react-router history prop. Now, you can use the exposed go or push functions outside of components or also inside.

Maybe my code can help you:

import {
   createBrowserHistory
} from "history";
import qs from "qs";

const history = createBrowserHistory();

history.location = {
   ...history.location,
   query: qs.parse(history.location.search.substr(1)),
   state: {},
};
history.listen(() => {
   history.location = {
      ...history.location,
      query: qs.parse(history.location.search.substr(1)),
      state: history.location.state || {},
   };
});

const {
   go,
   goBack,
   push,
   replace
} = history;

export {
   go,
   goBack,
   push,
   replace,
   getRedirectPath
};
export default history;
load more v
88%

The withRouter higher-order component will inject the history object as a prop of the component. This allows you to access the push and replace methods without having to deal with the context.,Use the withRouter higher-order component.,In 2.4 and above, use a higher order component to get the router as a prop of your component.

There is a new useHistory hook in React Router >5.1.0 if you are using React >16.8.0 and functional components.

import { useHistory } from "react-router-dom";

function HomeButton() {
  const history = useHistory();

  function handleClick() {
    history.push("/home");
  }

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}
load more v
72%

The primary way you programmatically navigate using React Router v5 is by using a <Redirect /> component.,🚨 Note this post is using React Router v5. If you’re using another version, find it below,After reading that, there’s at least a small chance that you hate it. Instead of using an imperative API (history.push), we’re using a declarative Redirect component. Again, the reason for this is because it aligns exactly with the principles of React itself.

function Register () {
  const [toDashboard, setToDashboard] = React.useState(false)

  if (toDashboard === true) {
    return <Redirect to='/dashboard'/>
  }

  return (
      <div>
        <h1>Register</h1>
        <Form afterSubmit={() => toDashboard(true)} />
      </div>
  )
}
load more v
65%

Just look at the code: https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/BrowserRouter.js,browserHistory is not exposed by react-router in v4, only in v2.,While this may be a very cutting edge way of doing new react components, the fact is the community is not used to them and beginners are certainly not either.

import {BrowserRouter} from 'react-router';
let root=<BrowserRouter>
                     //Some components
              </BrowserRouter>
 ReactDOM.render(Root, document.getElementById("app"))
load more v
75%

Pretag
 Pretag team - issue, fix, solve, resolve
40%

Telerik and Kendo UI are part of Progress product portfolio. Progress is the leading provider of application development and digital experience technologies.,React Router is designed to follow the ideology as mentioned earlier. Thus, programmatically navigating with React Router should, by definition, align with those three core concepts.,history.push() is another approach where we make use of the history props React Router provides while rendering a component.

import React, { useState } from 'react';
import { Redirect } from 'react-router-dom';
import { userLogin } from './userAction';
import Form from './Form';
const Login = () => {
 const [isLoggedIn, setIsLoggedIn] = useState(false);
  
 const handleLogin = async (userDetail) => {
  const success = await userLogin(userDetail);
  if(success) setIsLoggedIn(true);
 }
  
  if (isLoggedIn) {
   return <Redirect to='/profile' />
  }
  return (
   <>
    <h1>Login</h1>
    <Form onSubmit={handleLogin} />
   </>
  )
}
export default Login;
load more v
22%

This creates the navigations we need to go from one page to another within the app. Here’s a visual representation of what we are doing here. ,The hookrouter module provides a wrapper around the HTML anchor tag <a/> as <A/>. It is accessible as a React component and 100% feature compatible to the native <a/> tag. The only difference is that it pushes navigations to the history stack instead of actually loading a new page.,To this effect, we’ll be making references to the React Router and also to hooksrouter for demonstration purposes. First, let’s take a closer look at React Router.

Pretag
 Pretag team - issue, fix, solve, resolve
60%

Provides access to the history prop in React Router,A primary use case would be for programmatic routing with functions, like push, replace, etc.,Provides access to the location prop in React Router

// When you wanted to render the route and get router props for component
<Route path="/" component={Home} />


// Or when you wanted to pass extra props
<Route path="/" render={({ match }) => <Profile match={match} mine={true} />}>
<Route path="/">
   <Home />
</Route>
import { useHistory } from 'react-router-dom';

function Home() {
  const history = useHistory();
  return <button onClick={() => history.push('/profile')}>Profile</button>;
}
import { useLocation } from 'react-router-dom';

function Profile() {
  const location = useLocation();
  useEffect(() => {
    const currentPath = location.pathname;
    const searchParams = new URLSearchParams(location.search);
  }, [location]);
  return <p>Profile</p>;
}
import { useParams, Route } from 'react-router-dom';

function Profile() {
  const { name } = useParams();
  return <p>{name}'s Profile</p>;
}

function Dashboard() {
  return (
    <>
      <nav>
        <Link to={`/profile/ann`}>Ann's Profile</Link>
      </nav>
      <main>
        <Route path="/profile/:name">
          <Profile />
        </Route>
      </main>
    </>
  );
}
import { useRouteMatch, Route } from 'react-router-dom';

function Auth() {
  const match = useRouteMatch();
  return (
    <>
      <Route path={`${match.url}/login`}>
        <Login />
      </Route>
      <Route path={`${match.url}/register`}>
        <Register />
      </Route>
    </>
  );
}

For example, consider that you need your own profile to be rendered at /profile and somebody else’s profile if the URL contains the name of the person /profile/dan or /profile/ann. Without using the hook, you would either write a Switch, list both routes and customize them with props. But now, using the hook we can do this:

import {
  Route,
  BrowserRouter as Router,
  Link,
  useRouteMatch,
} from 'react-router-dom';

function Profile() {
  const match = useRouteMatch('/profile/:name');

  return match ? <p>{match.params.name}'s Profile</p> : <p>My own profile</p>;
}

export default function App() {
  return (
    <Router>
      <nav>
        <Link to="/profile">My Profile</Link>
        <br />
        <Link to={`/profile/ann`}>Ann's Profile</Link>
      </nav>
      <Route path="/profile">
        <Profile />
      </Route>
    </Router>
  );
}
load more v
48%

The primary way you programmatically navigate using React Router v5 is by using a <Redirect /> component.,Congrats! You now have the power to create nested routes with React Router v5. Tell your Mom, she’ll be proud .,Finally, we have a nice foundation to start talking about how we go about dealing with nested routes with React Router v5. Thanks for your patience .

Pretag
 Pretag team - issue, fix, solve, resolve

Other "outside-router" queries related to "Programmatic access to history (history.push etc) in react-router v5 outside of components"