I'm trying to set up routing in React v18 that restricts certain pages to only users who are logged in. I can't seem to get the function in the return
statement to work. Login
and Register
work OK. If I put another component outside the function, the same level as Login
and Register
, it works fine, too. But when the page loads, it should got to localhost/
, see there's no token, then route to /login
. Right now it just stays on localhost/
and shows an empty page. The warning in the console says "No routes match location '/' ". That is true, because the component with path "/" is in AppViews
and should be restricted. But it's not moving the user to `/login'. Why not? What am I missing?
export const MyApp = () => {
const [token, setTokenState] = useState(localStorage.getItem('token'))
const setToken = (newToken) => {
localStorage.setItem('token', newToken)
setTokenState(newToken)
}
return (
<>
<Routes>
{ <Route render={() => {
if (localStorage.getItem("app_token")) {
return <>
<Route>
<AppViews />
</Route>
</>
} else {
return <Navigate to="/login" />
}
}} />
}
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
</Routes>
</>
)
}
export default MyApp;
CodePudding user response:
In react-router-dom@6
the Route
component hasn't any render
prop. In other words, the render
prop is completely ignored and has no effect. All the routed content is rendered out on the element
prop. Use a ternary operator to conditionally render the redirect or the AppViews
component.
export const MyApp = () => {
const [token, setTokenState] = useState(localStorage.getItem('token'))
const setToken = (newToken) => {
localStorage.setItem('token', newToken)
setTokenState(newToken)
}
return (
<Routes>
<Route
path="/*"
element={localStorage.getItem("app_token")
? <AppViews />
: <Navigate to="/login" replace />
}
/>
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
</Routes>
);
}
It's more conventional to create a protected route component.
Example:
import { Navigate, Outlet } from 'react-router-dom';
const ProtectedRoute = () => {
const appToken = localStorage.getItem("app_token");
return appToken
? <Outlet />
: <Navigate to="/login" replace />
};
...
export const MyApp = () => {
const [token, setTokenState] = useState(localStorage.getItem('token'))
const setToken = (newToken) => {
localStorage.setItem('token', newToken)
setTokenState(newToken)
}
return (
<Routes>
<Route element={<ProtectedRoute />}>
<Route path="/*" element={<AppViews />} />
</Route>
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
</Routes>
);
}