184

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?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Hongbo Miao
  • 45,290
  • 60
  • 174
  • 267
  • 4
    This looks like a bug in the docs. Notice how [right in the section above that](https://reactrouter.com/docs/en/v6/upgrading/v5#upgrade-to-react-router-v51) 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 [`} />` is the new style](https://reactrouter.com/docs/en/v6/upgrading/v5#advantages-of-route-element). – Bergi Nov 07 '21 at 01:40
  • https://gist.github.com/mjackson/b5748add2795ce7448a366ae8f8ae3bb#not-server-rendering – Bergi Nov 07 '21 at 01:44
  • Also from https://gist.github.com/mjackson/d54b40a094277b7afdd6b81f51a0393f#get-started-upgrading-today: "*When you finally do upgrade to v6, convert ` ...}>` to `` and you're done.*" – Bergi Nov 07 '21 at 01:48
  • Thanks @Bergi I succeed by a little updates: `} />`, feel free to post as an answer! – Hongbo Miao Nov 07 '21 at 06:06

11 Answers11

341

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
RodolfoSilva
  • 4,684
  • 1
  • 18
  • 18
  • If you want to redirect outside react components or without hooks, check out [this answer](https://stackoverflow.com/a/70000286/1494454). – totymedli Feb 10 '22 at 06:56
  • 1
    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 `/`? – Douglas Gaskell Apr 24 '22 at 08:52
  • Worth noting that this has no SSR support for static routing – Neil May 11 '22 at 10:46
  • @RodolfoSilva but what if we also want to add a NotFound Page than what path we will add to the NotFound ? – Kashif Ali Jun 16 '22 at 14:25
  • 1
    @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. – RodolfoSilva Jun 16 '22 at 18:00
  • 1
    Is there any api docs on Navigate and replace? It seems that i should have stopped with the docs, but somehow ended here. – ColdHands Sep 19 '22 at 11:37
71

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Hamedo Esk
  • 735
  • 3
  • 3
  • 3
    It says useNavigator can be used only in the context of the router. It can't be used alone. – Zain Sadaqat Oct 16 '22 at 14:32
  • use this component inside an appropriate Router component: example: {...your routes here, which in turn reference the component in this answer} – Mattwmaster58 Aug 15 '23 at 04:55
14

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

8

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 />} />
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ayush Nanda
  • 81
  • 1
  • 2
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

Kumawat Lalit
  • 410
  • 4
  • 8
5
      <BrowserRouter>
        <Routes>
          <Route path="home" element={<Home />} />
          <Route path="about" element={<About />} />
          <Route index element={<Navigate to="/home" replace />} />
        </Routes>
      </BrowserRouter>
gyozo kudor
  • 6,284
  • 10
  • 53
  • 80
4
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>

    </>)
}
Joundill
  • 6,828
  • 12
  • 36
  • 50
3

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.

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

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;
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('/');
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ali Alizadeh
  • 326
  • 2
  • 6