I have some older React Router 5 code I am upgrading to use React Router 6 and have run into a problem with using a custom route that is used to do protected routes in conjunction with authentication.
First I have the routes in App.js
function App() {
return (
<Container>
<Row>
<Col className="text-center">
<h1>React Authentication Tutorial</h1>
<section id="navigation">
<a href="/">Home</a>
<a href="/free">Free Component</a>
<a href="/auth">Auth Component</a>
</section>
</Col>
</Row>
{/* create routes here */}
<Routes>
<Route exact path="/" component={Account} />
<Route exact path="/free" component={FreeComponent} />
<ProtectedRoutes path="/auth" component={AuthComponent} />
</Routes>
</Container>
);
}
In my ProtectedRoutes.js file as per the React Router 6 instructions I removed the Redirect and replaced with Navigate as you can see below. Basically this function as you can see moves the component the user tries to access into the function and then surmises if it is allowed and then just redirects them if they have a JWT token...but I am not doing something correctly because I get this error:
Error: [ProtectedRoutes] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment> at invariant
import React from "react";
import { Route, Navigate } from "react-router-dom";
import Cookies from "universal-cookie";
const cookies = new Cookies();
// receives component and any other props represented by ...rest
export default function ProtectedRoutes({ component: Component, ...rest }) {
return (
// this route takes other routes assigned to it from the App.js and return the same route if condition is met
<Route
{...rest}
render={(props) => {
// get cookie from browser if logged in
const token = cookies.get("TOKEN");
// returns route if there is a valid token set in the cookie
if (token) {
return <Component {...props} />;
} else {
// returns the user to the landing page if there is no valid token set
return (
<Navigate
replace to={{
pathname: "/",
state: {
// sets the location a user was about to access before being redirected to login
from: props.location,
},
}}
/>
);
}
}}
/>
);
}
For reference, here is the older React Router 5 code for the protected Route. Of course App.js was using Switch as well, but I spiffed that up to use Route and Routes so that is working good. Just a bit stuck on how to handle the redirect code using React Router 6 in my nifty ProtectedRoutes.js helped function.
import React from "react";
import { Route, Redirect } from "react-router-dom";
import Cookies from "universal-cookie";
const cookies = new Cookies();
// receives component and any other props represented by ...rest
export default function ProtectedRoutes({ component: Component, ...rest }) {
return (
// this route takes other routes assigned to it from the App.js and return the same route if condition is met
<Route
{...rest}
render={(props) => {
// get cookie from browser if logged in
const token = cookies.get("TOKEN");
// returns route if there is a valid token set in the cookie
if (token) {
return <Component {...props} />;
} else {
// returns the user to the landing page if there is no valid token set
return (
<Redirect
to={{
pathname: "/",
state: {
// sets the location a user was about to access before being redirected to login
from: props.location,
},
}}
/>
);
}
}}
/>
);
}