Reputation: 11981
Using protected.route
when a user login how can we make a user navigates to private routes like Dashboard
and ViewDetails
? If he is an admin user, then display Dashboard, else ViewDetails screen. Can someone please advise on this. I have added a codesandbox link for reference
Codesandbox link
https://codesandbox.io/s/tender-cerf-kss82?file=/src/components/Login.js
login.js
import { useState } from "react";
import { useHistory } from "react-router-dom";
const loginData = [
{ id: 1, email: "[email protected]", password: "admin123", access: "admin" },
{ id: 1, email: "[email protected]", password: "test123", access: "user" }
];
const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const history = useHistory();
const onSubmit = (email, password) => {
if (
email === loginData[0].email &&
password === loginData[0].password &&
loginData[0].access === "admin"
) {
history.push("/");
} else {
history.push("/ViewDetails");
}
};
return (
<div>
Login Page <br></br>
<input
type="text"
name="email"
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="text"
name="password"
onChange={(e) => setPassword(e.target.value)}
/>
<input type="button" value="submit" onClick={onSubmit(email, password)} />
</div>
);
};
export default Login;
protected.route.js
import React from "react";
import { Route, Redirect } from "react-router-dom";
export const ProtectedRoute = ({ component: Component, ...rest }) => {
return (
<Route
{...rest}
render={(props) => {
if (localStorage.getItem("loginEmail")) {
return <Component {...props} />;
} else {
return (
<>
<Redirect
to={{
pathname: "/login",
state: {
from: props.location
}
}}
/>
</>
);
}
}}
/>
);
};
App.js
import React, { useState } from "react";
import "./styles.css";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import Dashboard from "./components/Dashboard.js";
import Login from "./components/Login.js";
import ViewDetails from "./components/ViewDetails.js";
import UserLoginProvider from "./components/UserLoginProvider.js";
import UserProfileProvider from "./components/UserProfileProvider.js";
import ProtectedRoute from "./components/protected.route.js";
import ReactDOM from "react-dom";
//var ReactDOM = require("react-dom");
const App = () => {
return (
<BrowserRouter>
<UserLoginProvider>
<UserProfileProvider>
<>
<Switch>
<ProtectedRoute exact path="/" component={Dashboard} />
<ProtectedRoute path="/ViewDetails" component={ViewDetails} />
<Route path="/Login" component={Login} />
</Switch>
</>
</UserProfileProvider>
</UserLoginProvider>
</BrowserRouter>
);
};
ReactDOM.render(
React.createElement(App, null),
document.getElementById("root")
);
export default App;
Upvotes: 1
Views: 1373
Reputation: 202846
Here's an example suggestion.
Update the ProtectedRoute
component to take an access role
prop and conditionally render a Route
or Redirect
based on any role
stored in localStorage. If the role matches, return the expected route, if it exists and doesn't match then redirect home, otherwise redirect to login.
import { Route, Redirect } from "react-router-dom";
export const ProtectedRoute = ({ role, ...rest }) => {
const currentRole = JSON.parse(localStorage.getItem("role"));
if (currentRole === role) {
return <Route {...rest} />;
} else {
return (
<Redirect
to={{
pathname: currentRole ? "/" : "/login",
state: {
from: rest.location
}
}}
/>
);
}
};
Update Login
to handle saving an authenticated user's access
role into local storage and redirect back to the path they were originally attempting to access.
import { useHistory, useLocation } from "react-router-dom";
const Login = () => {
const history = useHistory();
const { state } = useLocation();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const onSubmit = (email, password) => {
const user = loginData.find(
(el) => el.email === email && el.password === password
);
if (user) {
localStorage.setItem("role", JSON.stringify(user.access));
history.replace(state.from ?? "/");
} else {
console.error("no user match found!");
}
};
return (
<div>
....
</div>
);
};
Update the protected routes you are rendering in your App
.
const App = () => {
return (
<UserLoginProvider>
<UserProfileProvider>
<Switch>
<ProtectedRoute
role="admin"
path="/dashboard"
component={Dashboard}
/>
<ProtectedRoute
role="user"
path="/viewDetails"
component={ViewDetails}
/>
<Route path="/Login" component={Login} />
<Route>
.... home page with nav links, etc...
</Route>
</Switch>
</UserProfileProvider>
</UserLoginProvider>
);
};
Upvotes: 1