soccerway
soccerway

Reputation: 11981

Using react hooks how can a user navigates to protected routes based on admin access

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

Answers (1)

Drew Reese
Drew Reese

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

Edit using-react-hooks-how-can-a-user-navigates-to-protected-routes-based-on-admin-ac

Upvotes: 1

Related Questions