232

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 documentation, it does have render for Route. How can I use it correctly?

4
  • 5
    This looks like a bug in the docs. Notice how right in the section above that they deprecated render in favour of children? But it looks like that section you were reading talks about upgrading from v5 to v5.1, they only removed render in v6. Looks like <Route element={<Navigate to="/" />} /> is the new style. Commented Nov 7, 2021 at 1:40
  • gist.github.com/mjackson/… Commented Nov 7, 2021 at 1:44
  • Also from gist.github.com/mjackson/…: "When you finally do upgrade to v6, convert <Route render={() => ...}> to <Route element={...}> and you're done." Commented Nov 7, 2021 at 1:48
  • Thanks @Bergi I succeed by a little updates: <Route path="*" element={<Navigate to="/" />} />, feel free to post as an answer! Commented Nov 7, 2021 at 6:06

13 Answers 13

397

I think you should use the no match route approach.

Check this in the documentation: 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>

To keep the history clean, you should set replace prop. This will avoid extra redirects after the user click back.

Sign up to request clarification or add additional context in comments.

6 Comments

If you want to redirect outside react components or without hooks, check out this answer.
What if / is a parent route to those others? How do you prevent / itself from being a route that can be navigated to? And instead redirect / to say /home when home is a child under /?
Worth noting that this has no SSR support for static routing 👍🏻
@KashifAli in that case, you should replace the Navigation componet with you custom Not Found screen. I don't think you will be able to have both using a wildcard path. But you can use a Nested approach to limit when the user should be redirected inside some path.
Is there any api docs on Navigate and replace? It seems that i should have stopped with the docs, but somehow ended here.
|
84

I found another way to do this:

import { useNavigate } from "react-router-dom";
let navigate = useNavigate();

useEffect(() => {
   if (LoggedIn){
      return navigate("/");
   }
},[LoggedIn]);

See Overview, Navigation.

2 Comments

It says useNavigator can be used only in the context of the router. It can't be used alone.
use this component inside an appropriate Router component: example: <BrowserRouter>{...your routes here, which in turn reference the component in this answer}</BrowserRouter>
21

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>
  );
}

Comments

9

In version 5 of React, i.e., react-router-dom, we had the Redirect component. But in version 6 of React it is updated to the Navigate components.

We can pass replace in these 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 />} />

Comments

8

FOR react-router VERSION 6

New example after editing----->(more simple easy to read)

import {BrowserRouter as Router,Routes,Route} from 'react-router-dom';
import Home from '../NavbarCompo/About';
import Contact from '../NavbarCompo/Contact';
import About from '../NavbarCompo/About';
import Login  from '../NavbarCompo/Login';
import Navbar from '../Navbar/Navbar';
import Error from '../pages/error';
import Products  from '../pages/products';
import Data from '../NavbarCompo/Data';

const Roter=()=>{
    return (
    <Router>

            <Navbar />
        <Routes>
            
            <Route path='/' element={<Home />} />
            <Route path='/about' element={<About />} />
            <Route path='/contact' element={<Contact />} />
            <Route path='/login' element={<Login />} />
            <Route path='/product/:id' element={<Products />} />
            <Route path='/data' element={<Data />} />
            <Route path ='*' element={<Error />} />
        </Routes>


    </Router>
    )
}
export default Roter;

Look at the example

import React from "react";
import Form from "./compo/form";
import ReactDOM from "react-dom/client";
import { createBrowserRouter, RouterProvider, Route,Routes,Navigate } from "react-router-dom";

const router = createBrowserRouter([
  {
    path: "/",
    element: <Form />
  },
  {
    path: "/about",
    element: <h1>hola amigo,you are in about section</h1>
  },
  {
    path:"*",
    element:<Navigate to="/" replace />
  }
]);

const root = ReactDOM.createRoot(document.getElementById("root"));

root.render(
  <React.StrictMode>
    <RouterProvider router={router}></RouterProvider>
  </React.StrictMode>
);

check this out https://reactrouter.com/en/main/start/overview

1 Comment

I mean for react-router v6 ,check this out reactrouter.com/en/main/start/overview
6
      <BrowserRouter>
        <Routes>
          <Route path="home" element={<Home />} />
          <Route path="about" element={<About />} />
          <Route index element={<Navigate to="/home" replace />} />
        </Routes>
      </BrowserRouter>

Comments

5
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>

    </>)
}

Comments

4

You can use the Navigate component from react-router-dom to achieve the same effect as Redirect. First, import { Navigate } from 'react-router-dom' Here's an example:

<Route path="/" element={<Navigate to="/todos" replace />} />

The replace is used to replace the current history entry instead of adding a new entry.

Comments

4

I was facing the issue of redirecting the user to /login if the user tries to access the dashboard without login .First I use the

Navigate('/login')

but it's not the correct way as it render the page first and then redirects to login so then I used another approach which is as follow.

    const auth  = useContext(AuthContext);

if(!auth?.loggedin){
  
    return <Navigate to='/login'></Navigate>
}return children;

Comments

2
import { useState } from "react"
import { Navigate } from "react-router-dom"
const [login, setLogin] = useState(true)
return (<>
{!login && <Navigate to="/login" />}
<>)

Comments

1

In React Router v6, we can use <Navigate /> like the other answer to redirect.

However, in that case, if we have used params/slug for example /users/:id in the path then it will redirect from /users/10 to /new-path/:id instead of /new-path/10.

To resolve such cases, we can have a custom component like below:

// Redirect.tsx

import { useEffect } from 'react'
import { generatePath, useNavigate, useParams } from 'react-router-dom'

function Redirect({ to }: { to: string }) {
  const navigate = useNavigate()
  const params = useParams()

  useEffect(() => {
    navigate(generatePath(to, params), { replace: true })
  })

  return null
}

export default Redirect

And we can import it like:

<Route path="/users/:id" element={<Redirect to="/new-path/:id" />} />

Comments

0

For class components, at the first you should make a functional component, and then use HOC technical to use useNavigate React hook.

Like this:

File withrouter.js

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

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

Then use it in other class components like this:

export default withRouter(Signin);

And use props for redirect like this:

this.props.navigate('/');

Comments

-2

For react-router-dom version 5.3 I used useHistory().

Sample code

import React from 'react';
import { useHistory } from 'react-router-dom';

function MyComponent() {
  const history = useHistory();

  const redirectToOverview = () => {
    // Use the history.push method to navigate to /app/overview
    history.push('/app/overview');
  };

  return (
    <div>
      {/* When this button is clicked, redirectToOverview will be called */}
      <button onClick={redirectToOverview}>Go to Overview</button>
    </div>
  );
}

export default MyComponent;

1 Comment

That is not a redirect from one route to another. That is just standard navigation.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.