How to redirect in React Router v6?

Viewed 185092

I am trying to upgrade to React Router v6 (react-router-dom 6.0.1).

Here is my updated code:

import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';

<BrowserRouter>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/lab" element={<Lab />} />
    <Route render={() => <Navigate to="/" />} />
  </Routes>
</BrowserRouter>

The last Route is redirecting the rest of paths to /.

However, I got an error

TS2322: Type '{ render: () => Element; }' is not assignable to type 'IntrinsicAttributes & (PathRouteProps | LayoutRouteProps | IndexRouteProps)'.   Property 'render' does not exist on type 'IntrinsicAttributes & (PathRouteProps | LayoutRouteProps | IndexRouteProps)'.

However, based on the doc, it does have render for Route. How to use it correctly?

7 Answers

I think you should use the no match route approach.

Check this in the documentation.

https://reactrouter.com/docs/en/v6/getting-started/tutorial#adding-a-no-match-route

import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';

<BrowserRouter>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/lab" element={<Lab />} />
    <Route
        path="*"
        element={<Navigate to="/" replace />}
    />
  </Routes>
</BrowserRouter>

Update - 18/03/2022

To keep the history clean, you should set replace prop. This will avoid extra redirects after the user click back. Thanks @Paul for this tip.

Create the file RequireAuth.tsx

import { useLocation, Navigate } from "react-router-dom";
import { useAuth } from "../hooks/Auth";

export function RequireAuth({ children }: { children: JSX.Element }) {
  let { user } = useAuth();
  let location = useLocation();

  if (!user) {
    return <Navigate to="/" state={{ from: location }} replace />;
  } else {
    return children;
  }
}

Import the component to need user a private router:

import { Routes as Switch, Route } from "react-router-dom";

import { RequireAuth } from "./RequireAuth";
import { SignIn } from "../pages/SignIn";
import { Dashboard } from "../pages/Dashboard";

export function Routes() {
  return (
    <Switch>
      <Route path="/" element={<SignIn />} />
      <Route
        path="/dashboard"
        element={
          <RequireAuth>
            <Dashboard />
          </RequireAuth>
        }
      />
    </Switch>
  );
}

In V5 of react ie. react-router-dom we had Redirect component. But in V6 of react it is updated to Navigate components.

We can pass replace in this components to avoid unnecessary redirects on clicking back and forward option.

Demonstration for usage is attached below :

<Route  path="/" element={user ? <Home /> : <Register />} />
<Route path="/login" element={user ? <Navigate to="/" replace /> :  <Login />}  />
<Route path = "/register" element={user ? <Navigate to="/" replace /> :  <Register />} />
import { useState } from "react"
import { Navigate } from "react-router-dom"
const [login, setLogin] = useState(true)
return (<>
{!login && <Navigate to="/login" />}
<>)
import { useNavigate } from "react-router-dom";
import { Button } from "@mui/material";

const component =()=>{

    const navigate = useNavigate();

    const handelGoToLogin = () => {
        navigate('/auth/login')
    }

    return(<>
        //.........
    
        <Button onClick={handelGoToLogin} variant="outlined" color="primary" size="large" fullWidth>
             Back
        </Button>

    </>)
}

for class components, at the first you should make a functional component then use HOC technical to use useNavigate react hook. like this:

withrouter.js:

import {useNavigate} from 'react-router-dom';

export const withRouter = WrappedComponent => props => {
    return (<WrappedComponent {...props} navigate={useNavigate()}/>);
};

then use use it in other class components like this:

export default withRouter(Signin);

and use props for redirect like this:

this.props.navigate('/');
Related