- Published on
How to Programmatically Navigate Using React Router
- Authors
- Name
- Ripal & Zalak
Introduction
In React Router, navigation is commonly handled using the <Link> component. However, there are situations where programmatic navigation is required, such as navigating based on a user action like a button click or a dropdown selection. This blog explores the modern and legacy approaches to programmatically navigate using React Router.
React Router v6: Using useNavigate
React Router v6 introduced the useNavigate hook, which replaces the deprecated useHistory hook. This hook provides a simple way to programmatically navigate within your application.
Example
import { useNavigate } from 'react-router-dom'
function HomeButton() {
const navigate = useNavigate()
function handleClick() {
navigate('/home')
}
return (
<button type="button" onClick={handleClick}>
Go Home
</button>
)
}
Key Features of useNavigate:
- Accepts a path to navigate to.
- Allows options like
replace: trueto replace the current history entry instead of adding a new one.
Advanced Example with State
You can pass state along with navigation:
navigate('/profile', { state: { userId: 123 } })
To access this state in the target component:
import { useLocation } from 'react-router-dom'
function ProfilePage() {
const location = useLocation()
console.log(location.state.userId)
}
React Router v5: Using useHistory
For applications using React Router v5, the useHistory hook is used for programmatic navigation.
Example
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>
)
}
Differences Between useNavigate and useHistory
While useHistory works similarly to useNavigate, it is now deprecated in favor of the cleaner and more feature-rich useNavigate.
Legacy Approaches in React Router v4
1. Using withRouter
The withRouter higher-order component provides access to the history object as a prop.
import { withRouter } from 'react-router-dom'
const Button = withRouter(({ history }) => (
<button type="button" onClick={() => history.push('/new-location')}>
Click Me
</button>
))
2. Using <Route> Component
You can render a pathless <Route> to always match the current location and use the history prop it provides.
import { Route } from 'react-router-dom'
const Button = () => (
<Route
render={({ history }) => (
<button type="button" onClick={() => history.push('/new-location')}>
Click Me
</button>
)}
/>
)
Legacy Context API (Not Recommended)
In earlier versions of React Router, the context API could be used to access the history object. However, this approach is not recommended as it tightly couples components to React Router’s implementation.
Example
class Button extends React.Component {
static contextTypes = {
history: PropTypes.shape({
push: PropTypes.func.isRequired,
}),
}
render() {
return (
<button type="button" onClick={() => this.context.history.push('/new-location')}>
Click Me
</button>
)
}
}
Best Practices for Programmatic Navigation
- Use Hooks for Modern React Projects: Prefer
useNavigatefor React Router v6 oruseHistoryfor v5. - Avoid Legacy Approaches: Context-based navigation and mixins are outdated and should be avoided.
- Centralize Navigation Logic: For complex apps, consider creating a reusable navigation utility or service.
- Ensure Accessibility: Always ensure navigation methods maintain accessibility standards, such as using buttons for click actions.
Conclusion
Programmatic navigation in React Router has evolved significantly over time. With the modern useNavigate hook, navigating programmatically has become cleaner and more intuitive. By understanding these approaches and best practices, you can effectively handle navigation in any React Router version.
