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