Published: March 30 2023

React Router v6 - Redirect with Navigate and useNavigate

Tutorial built with React 18.2 and React Router 6.8.1

This is a quick post on how to redirect with React Router v6 using the Navigate component and useNavigate() hook function.

The below code snippets are from a React auth tutorial I posted recently, full documentation and live demo are avaiable at React 18 + Redux - User Registration and Login Example & Tutorial.

Redirect with the <Navigate /> React Router component

Below is an example React PrivateRoute component that redirects unauthorized users to the login page with the React Router 6 Navigate component on line 11.

import { Navigate, Outlet } from 'react-router-dom';
import { useSelector } from 'react-redux';

export { PrivateRoute };

function PrivateRoute() {
    const auth = useSelector(x => x.auth.value);

    if (!auth) {
        // not logged in so redirect to login page
        return <Navigate to="/account/login" />

    // authorized so return outlet for child routes
    return <Outlet />;

Redirect with the useNavigate() React Router hook

Below is an example React Register component that redirects users to the login page after successful registration with the React Router 6 useNavigate() hook function.

The hook is called on line 13 to create the navigate() function instance. The navigate() function is then called on line 39 to redirect to the login page after successful registration.

import { Link, useNavigate } from 'react-router-dom';
import { useForm } from "react-hook-form";
import { yupResolver } from '@hookform/resolvers/yup';
import * as Yup from 'yup';
import { useDispatch } from 'react-redux';

import { userActions, alertActions } from '_store';

export { Register };

function Register() {
    const dispatch = useDispatch();
    const navigate = useNavigate();

    // form validation rules 
    const validationSchema = Yup.object().shape({
        firstName: Yup.string()
            .required('First Name is required'),
        lastName: Yup.string()
            .required('Last Name is required'),
        username: Yup.string()
            .required('Username is required'),
        password: Yup.string()
            .required('Password is required')
            .min(6, 'Password must be at least 6 characters')
    const formOptions = { resolver: yupResolver(validationSchema) };

    // get functions to build form with useForm() hook
    const { register, handleSubmit, formState } = useForm(formOptions);
    const { errors, isSubmitting } = formState;

    async function onSubmit(data) {
        try {
            await dispatch(userActions.register(data)).unwrap();

            // redirect to login page and display success alert
            dispatch(alertActions.success({ message: 'Registration successful', showAfterRedirect: true }));
        } catch (error) {

    return (
        <div className="card m-3">
            <h4 className="card-header">Register</h4>
            <div className="card-body">
                <form onSubmit={handleSubmit(onSubmit)}>
                    <div className="mb-3">
                        <label className="form-label">First Name</label>
                        <input name="firstName" type="text" {...register('firstName')} className={`form-control ${errors.firstName ? 'is-invalid' : ''}`} />
                        <div className="invalid-feedback">{errors.firstName?.message}</div>
                    <div className="mb-3">
                        <label className="form-label">Last Name</label>
                        <input name="lastName" type="text" {...register('lastName')} className={`form-control ${errors.lastName ? 'is-invalid' : ''}`} />
                        <div className="invalid-feedback">{errors.lastName?.message}</div>
                    <div className="mb-3">
                        <label className="form-label">Username</label>
                        <input name="username" type="text" {...register('username')} className={`form-control ${errors.username ? 'is-invalid' : ''}`} />
                        <div className="invalid-feedback">{errors.username?.message}</div>
                    <div className="mb-3">
                        <label className="form-label">Password</label>
                        <input name="password" type="password" {...register('password')} className={`form-control ${errors.password ? 'is-invalid' : ''}`} />
                        <div className="invalid-feedback">{errors.password?.message}</div>
                    <button disabled={isSubmitting} className="btn btn-primary">
                        {isSubmitting && <span className="spinner-border spinner-border-sm me-1"></span>}
                    <Link to="../login" className="btn btn-link">Cancel</Link>


Need Some React Help?

Search fiverr for freelance React developers.

Follow me for updates

On Twitter or RSS.

When I'm not coding...

Me and Tina are on a motorcycle adventure around Australia.
Come along for the ride!


Supported by