Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to perform authentication with React hooks and react-router

I am trying to authenticate user on each route change with react-router-dom and react hooks. The idea is that each time user navigates to a route the system makes an api call and authenticate the user. I need to achieve this because I use react-redux, and on each window reload the redux state is not persisted. So i need to set the isLoggedNow prop to true again:

const PrivateRoute = ({
  component: Component,
  checkOnEachRoute: checkReq,
  isUserLogged,
  ...rest
}) => {
  const [isLoggedNow, setLogged] = useState(isUserLogged);
  useEffect(
    () => {
      const fetchStatus = async () => {
        try {
          await selectisUserLogged();
          setLogged(true);
        } catch (error) {
          console.log(error);
        }
      };
      fetchStatus();
    },
    [isUserLogged],
  );
  return (
    <Route
      {...rest}
      render={props =>
        isLoggedNow ? (
          <div>
            <Component {...props} />
          </div>
        ) : (
          <Redirect
            to={{
              pathname: '/login',
            }}
          />
        )
      }
    />
  );
};

I then would use the above PrivateRoute like this:

function App(props) {
  return (
    <div>
      <Switch location={props.location}>
        <Route exact path="/login" component={Login} />
        <PrivateRoute exact path="/sidebar" component={Sidebar} />
      </Switch>
    </div>
  );
}

First the isUserLogged is true, but after window reload I get an error Warning: Can't perform a React state update on an unmounted component. So how can I achieve this, so on each window reload I authenticate the user? I am looking for some kind of componentWillMount.

like image 204
user1665355 Avatar asked Mar 26 '19 13:03

user1665355


People also ask

How do I authenticate my router in react JS?

import { Navigate, Outlet } from "react-router-dom"; import { useAuth } from "../hooks/useAuth"; export const HomeLayout = () => { const { user } = useAuth(); if (user) { return <Navigate to="/dashboard/profile" />; } return ( <div> <nav> <Link to="/">Home</Link> <Link to="/login">Login</Link> </nav> <Outlet /> </div> ...

How react Hooks can replace react router?

The Hooks alternative to handling URL parameters It reads all URL parameters and puts them into an object. It does this using the keys you defined in the routes object. Then all the named parameters will be forwarded to your route result function as a combined object.

Is useMemo react hook?

React has a built-in hook called useMemo that allows you to memoize expensive functions so that you can avoid calling them on every render. You simple pass in a function and an array of inputs and useMemo will only recompute the memoized value when one of the inputs has changed.


1 Answers

Something like this works (where isUserLogged is a prop from redux):

function PrivateRoute({ component: Component, isUserLogged, ...rest }) {
  const [isLoading, setLoading] = useState(true);
  const [isAuthenticated, setAuth] = useState(false);
  useEffect(() => {
    const fetchLogged = async () => {
      try {
        setLoading(true);
        const url = new URL(fetchUrl);
        const fetchedUrl = await fetchApi(url);
        setAuth(fetchedUrl.body.isAllowed);
        setLoading(false);
      } catch (error) {
        setLoading(false);
      }
    };
    fetchLogged();
  }, []);
  return (
    <Route
      {...rest}
      render={props =>
        // eslint-disable-next-line no-nested-ternary
        isUserLogged || isAuthenticated ? (
          <Component {...props} />
        ) : isLoading ? (
          <Spin size="large" />
        ) : (
          <Redirect
            to={{
              pathname: '/login',
            }}
          />
        )
      }
    />
  );
}
like image 185
user1665355 Avatar answered Oct 18 '22 09:10

user1665355