88

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?

Henry Ecker
  • 31,792
  • 14
  • 29
  • 50
Hongbo Miao
  • 38,184
  • 54
  • 150
  • 228
  • 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

5 Answers5

190

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.

RodolfoSilva
  • 3,056
  • 1
  • 17
  • 16
  • 4
    Thank you so much brother. Your answer saved me. For a whole week I have been trying to find the exact syntax replacement of render prop in RRD5 and finally after days of research I found your answer. Much appreciated <3 – Faraz Zaidi Dec 19 '21 at 19:41
  • 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
  • 3
    It's better to use ``, otherwise a new entry is added to the history and if you try to navigate back you're redirected again, so you're stuck. – Paul Mar 18 '22 at 13:25
  • 1
    Thanks @Paul, makes sense, I'll update the answer. – RodolfoSilva Mar 18 '22 at 13:49
  • 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
32

I found another way to do this:

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

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

https://reactrouter.com/docs/en/v6/getting-started/overview#navigation

Hamedo Esk
  • 329
  • 2
  • 3
7

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

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

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 />} />