Issue
<BrowserRouter>
<Switch>
{authLogin ? (
<>
<Route path="/dashboard" component={Dashboard} exact />
<Route exact path="/About" component={About} />
</>
) : (
<Route path="/" component={Login} exact />
)}
<Route component={PageNotFound} />
</Switch>
</BrowserRouter>
The Switch
doesn’t handle rendering anything other than Route
and Render
components. If you want to “nest” like this then you need to wrap each in generic routes, but that is completely unnecessary.
Your login component also doesn’t handle redirecting back to any “home” page or private routes that were originally being accessed.
Solution
react-router-dom
v5
Create a PrivateRoute
component that consumes your auth context.
const PrivateRoute = (props) => {
const location = useLocation();
const { authLogin } = useContext(globalC);
console.log("authLogin", authLogin);
return authLogin ? (
<Route {...props} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: location }
}}
/>
);
};
Update your Login
component to handle redirecting back to the original route being accessed.
export default function Login() {
const location = useLocation();
const history = useHistory();
const { authLogin, loginData } = useContext(globalC);
if (authLogin) {
const { from } = location.state || { from: { pathname: "/" } };
history.replace(from)
}
return (
<div
style={{ height: "100vh" }}
className="d-flex justify-content-center align-items-center"
>
<button type="button" onClick={loginData} className="btn btn-primary">
Login
</button>
</div>
);
}
Render all your routes in a “flat list”
function Routes() {
return (
<BrowserRouter>
<Switch>
<PrivateRoute path="/dashboard" component={Dashboard} />
<PrivateRoute path="/About" component={About} />
<Route path="/login" component={Login} />
<Route component={PageNotFound} />
</Switch>
</BrowserRouter>
);
}
react-router-dom
v6
In version 6 custom route components have fallen out of favor, the preferred method is to use an auth wrapper component.
import { Navigate, Outlet } from 'react-router-dom';
const PrivateRoutes = () => {
const location = useLocation();
const { authLogin } = useContext(globalC);
console.log("authLogin", authLogin);
return authLogin
? <Outlet />
: <Navigate to="/login" replace state={{ from: location }} />;
}
…
<BrowserRouter>
<Routes>
<Route path="/" element={<PrivateRoutes />} >
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/about" element={<About />} />
</Route>
<Route path="/login" element={<Login />} />
<Route path="*" element={<PageNotFound />} />
</Routes>
</BrowserRouter>