Recommand · May 21, 2021 0

Render route in React router dom after useEffect

I need to render the component after the useEffect checks if an user has the required role, but it always redirect me because it execute first the render function and then the useEffect

Here’s my code:

import { Route, Redirect } from 'react-router-dom';
import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { checkIfUserHasRequiredRole } from '../../utility/utility';
import PathConst from '../../utils/PathConst';

const AuthRoute = ({
  Component, path, exact = false, isAuthenticated, requiredRoles,
}) => {
  const [userHasRequiredRole, setUserHasRequiredRole] = useState(false);
  const roles = useSelector((state) => state.role.roles);
  const isAuthed = isAuthenticated;

  useEffect(() => {
    if (roles) {
      const userRole = checkIfUserHasRequiredRole(requiredRoles, roles);
      setUserHasRequiredRole(userRole);
    }
  }, [roles]);

  return (
    <Route
      exact={exact}
      path={path}
      render={() => (
        isAuthed && userHasRequiredRole ? (<Component />)
          : (
            <Redirect
              to={PathConst.toLoginPage}
            />
          ))}
    />

  );
};

export default AuthRoute;

The function ‘checkIfUserHasRequiredRole’ returns true but ‘useHasRequiredRole’ is still false when it trigger the if statement. I also tried using the same useEffect function with no dependencies.
How can I manage it?

You could do with your setup, but that requires additional render so that userHasRequiredRole is updated and take effect.

Since you can figure out what you need based on roles, you could,

import { useHistory } from "react-router-dom";

  const history = useHistory();

  useEffect(() => {
    if (roles) {
      const userRole = checkIfUserHasRequiredRole(requiredRoles, roles);
      if (this role is not good) {      
        history.push(PathConst.toLoginPage)
      }
    }
  }, [roles])