How to programmatically change a route in Next.js
By Flavio Copes
Learn how to programmatically change a route in Next.js with the useRouter hook and router.push(), or the Router object when you are outside a component.
To programmatically change a route in Next.js you call router.push(), passing the URL you want to navigate to. It performs a client-side navigation, the same kind you get when clicking a Link component.
In a component, you get the router object with the useRouter hook:
import { useRouter } from 'next/router'
//...
const router = useRouter()
router.push('/dashboard')
This is what you use when the navigation is a consequence of some logic, not a click on a link. After a form submission, after a successful login, after a countdown ends.
Sometimes you can’t use the hook, for example when you’re not in a React component, maybe in a utility function. Hooks only work inside components.
In that case, import the global Router object:
import Router from 'next/router'
Router.push('/dashboard')
How do you pass query parameters?
Instead of building the URL string by hand, you can pass an object with pathname and query:
router.push({
pathname: '/products',
query: { category: 'books' },
})
This navigates to /products?category=books. Handy when the values come from variables and you don’t want to worry about escaping them.
push() or replace()?
router.push() adds an entry to the browser history. The user can press back and return to the previous page.
Sometimes that’s wrong. After a login, pressing back should not show the login form again. Use router.replace() in those cases:
router.replace('/dashboard')
Same navigation, but the current history entry gets replaced instead of a new one being added.
Be careful with redirects during render
A common mistake is calling router.push() directly in the component body, to send away users who shouldn’t see a page. That code runs while React is rendering, and it also runs on the server, where there’s no browser to navigate.
Put the call inside useEffect instead, so it runs in the browser after the component mounts:
useEffect(() => {
if (!user) {
router.push('/login')
}
}, [user])
The component renders once, the effect runs, and the user gets redirected.
Related posts about next: