In earlier versions of React Router, you had to create your own history instance, but in v4 the <BrowserRouter>, <HashRouter>, and <MemoryRouter> components will create a browser, hash, and memory instances for you. React Router makes the properties and methods of the history instance associated with your router available through the context, under the router object. The <Route> component isn't just for matching locations. You can render a pathless route and it will always match the current location. The <Route> component passes the same props as withRouter, so you will be able to access the history methods through the history prop. 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.
import { Route } from 'react-router-dom'
const Button = () => (
<Route render={({ history}) => (
<button
type='button'
onClick={() => { history.push('/new-location') }}
>
Click Me!
</button>
)} />
)
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>
);
}
import { withRouter } from 'react-router-dom'
// this also works with react-router-native
const Button = withRouter(({ history }) => (
<button
type='button'
onClick={() => { history.push('/new-location') }}
>
Click Me!
</button>
))
But you probably should not
The last option is one that you should only use if you feel comfortable working with React's context model (React's Context API is stable as of v16).
const Button = (props, context) => (
<button
type='button'
onClick={() => {
// context.history.push === history.push
context.history.push('/new-location')
}}
>
Click Me!
</button>
)
// you need to specify the context type so that it
// is available within the component
Button.contextTypes = {
history: React.PropTypes.shape({
push: React.PropTypes.func.isRequired
})
}
TL;DR: You can use the new useNavigate
hook.
import {
useNavigate
} from "react-router-dom";
function Component() {
let navigate = useNavigate();
// Somewhere in your code, e.g. inside a handler:
navigate("/posts");
}
React Router is used for Client-Side Routing of resources. In this guide, we've taken a quick look at how you can programmatically navigate an application using React Router as well as how to transfer states between routes when you do. In this guide, we'll take a look at how to create routes in a React application, programmatically navigate between routes, as well as send and retrieve data between them, using React Router. React is a massively popular library for front-end development used to create highly responsive user interfaces, and naturally, it has its own Router, which performs Client-Side Routing - the react-router-dom.
Let's start out by creating a simple React application via the command line:
$ npx create - react - app router - sample
Once created, let's move into the project's directory, and start the application:
$ cd router - sample $ npm start
As usual, installing a package using npm
is as simple as running a single command:
$ npm install react - router - dom
Now, let's update the src/index.js
page and import About
from the file we've just created. Within the <BrowserRouter>
tag, we'll define our routes and components associated with them:
import { render } from "react-dom";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import App from "./App";
import About from "./About";
render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
<Route path="about" element={<About />} />
</Routes>
</BrowserRouter>,
document.getElementById("root")
);
Finally, let's adapt the App.js
file, which will, again, be the main entry point for the application and serve our home page:
import { Link } from "react-router-dom";
function App() {
return (
<div className="App">
<h1>Welcome to my react app!</h1>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusamus,
pariatur?
</p>
<br />
<Link to="/about">About Page</Link>
</div>
);
}
export default App;
To programmatically navigate means to use JavaScript, i.e. program code, a function or method call. If you just want a straight-up hyperlink then your best bet is <Link to="/some-url" />, otherwise here we go… React Router provides the <NavLink> element for us to declaratively navigate around our applications, it renders an <a href=""> for us ... How to programmatically navigate with React Router v6 and the new useNavigate hook. Inside our Hello component, we’ll import the useNavigate hook from React Router and call it at the top of the functional component.
import * as React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Hello from './Hello';
import Goodbye from './Goodbye';
const App = () => (
<Router>
<Routes>
<Route exact path="/" element={<Hello />} />
<Route path="/goodbye" element={<Goodbye />} />
</Routes>
</Router>
);
export default App;
import * as React from 'react';
import { useNavigate } from 'react-router-dom';
const Hello = () => {
const navigate = useNavigate();
const handleClick = () => navigate('/goodbye');
return (
<button type="button" onClick={handleClick}>
Goodbye
</button>
);
};
export default Hello;
const GoBack = () => {
const navigate = useNavigate();
const handleClick = () => navigate(-1);
return (
<button type="button" onClick={handleClick}>
Go Back ⏪
</button>
);
};
declare function useNavigate(): NavigateFunction;
interface NavigateFunction {
(
to: To,
options ? : {
replace ? : boolean;
state ? : any;
relative ? : RelativeRoutingType;
}
): void;
(delta: number): void;
}
import React from 'react';
import { useHistory } from 'react-router-dom';
const Hello = () => {
const history = useHistory();
const handleClick = () => history.push('/goodbye');
return (
<button type="button" onClick={handleClick}>
Goodbye
</button>
);
};
export default Hello;
The primary way you programmatically navigate using React Router v4+ is by using a <Redirect /> component, and it’s a recommended method that helps the user navigate between routes. 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. The main focus of this article was to share how you can safely navigate between components using the React Router package.
Here’s a code example of how to use the Redirect component.
Codesandbox: https://codesandbox.io/s/gallant-meitner-bshng?file=/src/App.js
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;
The push
method is essential and is used to push a path as a route to the history stack, which executes as Last In First Out (LIFO). This causes the app to redirect to the last route added, thereby redirecting the user to a specified route. The example below assumes the component is rendered with React Router.
Codesandbox: https://codesandbox.io/s/angry-saha-djh3z?file=/src/App.js
import React from "react";
import { userLogin } from "./userAction";
import Form from "./Form";
const Login = props => {
const handleLogin = async userDetail => {
const success = await userLogin(userDetail);
if (success) props.history.push("/profile");
};
return (
<>
<h1>Login</h1>
<Form onSubmit={handleLogin} />
</>
);
};
export default Login;
We mentioned earlier that for a component to have access props.history.push
it must have been rendered with React Router. There are cases where this might not be the case. Thus, we render a component ourselves. To make the history
property available to the component, the React Router team created the Higher Order Component (HOC) withRouter. Wrapping a component with this HOC exposes the properties as well.
Codesandbox: https://codesandbox.io/s/silent-rain-l19lg?file=/src/App.js:0-442
import React from 'react';
import { withRouter } from 'react-router-dom';
import { userLogin } from './userAction';
import Form from './Form';
const Login = (props) => {
const handleLogin = async (userDetail) => {
const success = await userLogin(userDetail);
if(success) props.history.push('/profile');
}
return (
<>
<h1>Login</h1>
<Form onSubmit={handleLogin} />
</>
)
}
export default withRouter(Login);
The primary way you programmatically navigate using React Router is by using a <Navigate /> component. Now I know what you're thinking - how could navigating with a component be a good idea? But let's first look at an example, and then we'll walk through why this isn't as crazy as it may first appear. There are two ways to programmatically navigate with React Router - <Navigate /> and navigate(). React Router also comes with a useNavigate Hook which gets you access to navigate - React Router's imperative API for programmatically navigating.
import { Navigate } from "react-router-dom";
function Register() { const [toDashboard, setToDashboard] = React.useState(false);
if (toDashboard === true) { return <Navigate to="/dashboard" />; }
return ( <div> <h1>Register</h1> <Form afterSubmit={() => toDashboard(true)} /> </div> );}
import { useNavigate } from 'react-router-dom
function Register () { const navigate = useNavigate()
return ( <div> <h1>Register</h1> <Form afterSubmit={() => navigate('/dashboard')} /> </div> )}
Navigate to a specific URL. history.push("/about") Navigate to the previous page. That is the equivalent of the browser back button. history.push(-1) The react-router-dom V6 useNavigate allows three basic navigation types. The usage is const navigate = useNavigate() This article explains how to navigate the React router programmatically. I have presented examples in react-router-dom v5 and v6.
import { BrowserRouter, Link, Route, Routes, useNavigate } from 'react-router-dom';
export const App = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />}/>
<Route path="contact" element={<Contact />} />
</Routes>
</BrowserRouter>
);
}
export default App;
const Home = () =>{
const navigate = useNavigate();
const navigateTo = (url: string) => {
navigate(url)
}
return(
<div>
<p>Home</p>
<p><button onClick={() => navigateTo("about")}>Programatically Navigate to About</button></p>
<p><Link to="/contact">Contact</Link></p>
</div>
)
}
const About = () =>{
const navigate = useNavigate();
const navigateTo = (url: string) => {
navigate(url)
}
return(
<div>
<p>About</p>
<p><button onClick={() => navigateTo("/")}>Programatically Navigate to Home</button></p>
<p><Link to="/contact">Contact</Link></p>
</div>
)
}
const Contact = () =>{
const navigate = useNavigate();
const navigateTo = (url: string) => {
navigate(url)
}
return(
<div>
<p>Contact</p>
<p><Link to="/">Home</Link></p>
<p><button onClick={() => navigateTo("/about")}>Programatically Navigate to About</button></p>
</div>
)
}
import { Switch , Link, Route, useHistory, BrowserRouter } from "react-router-dom"
export const App = () => {
return (
<BrowserRouter>
<Switch>
<Route path="/"><Home/></Route>
<Route path="about"><About /></Route>
<Route path="contact"><Contact /></Route>
</Switch>
</BrowserRouter>
);
}
export default App;
const Home = () =>{
const history = useHistory();
function navigateTo(url: string) {
history.push(url);
}
return(
<div>
<p>Home</p>
<p><button onClick={() => navigateTo("about")}>Programatically Navigate to About</button></p>
<p><Link to="/contact">Contact</Link></p>
</div>
)
}
const About = () =>{
const history = useHistory();
function navigateTo(url: string) {
history.push(url);
}
return(
<div>
<p>About</p>
<p><button onClick={() => navigateTo("/")}>Programatically Navigate to Home</button></p>
<p><Link to="/contact">Contact</Link></p>
</div>
)
}
const Contact = () =>{
const history = useHistory();
function navigateTo(url: string) {
history.push(url);
}
return(
<div>
<p>Contact</p>
<p><Link to="/">Home</Link></p>
<p><button onClick={() => navigateTo("/about")}>Programatically Navigate to About</button></p>
</div>
)
}
There are three different ways to achieve programmatic routing/navigation within components. The withRouter() higher-order function will inject the history object as a prop of the component. This object provides push() and replace() methods to avoid the usage of context. Using the withRouter() higher-order function: The <Route> component passes the same props as withRouter(), so you will be able to access the history methods through the history prop.
import { withRouter } from 'react-router-dom'; // this also works with 'react-router-native'
const Button = withRouter(({ history }) => ( <button type="button" onClick={() => { history.push('/new-location'); }} > {'Click Me!'} </button>));
import { Route } from 'react-router-dom';
const Button = () => ( <Route render={({ history }) => ( <button type="button" onClick={() => { history.push('/new-location'); }} > {'Click Me!'} </button> )} />);
const Button = (props, context) => ( <button type="button" onClick={() => { context.history.push('/new-location'); }} > {'Click Me!'} </button>);
Button.contextTypes = { history: React.PropTypes.shape({ push: React.PropTypes.func.isRequired, }),};