Search code examples
javascriptreactjsuse-effect

useEffect with many dependencies


I am trying to fetch employees and here is what I am trying to do using useEffect

function AdminEmployees() {
  const navigate = useNavigate();
  const dispatch = useDispatch();

  // fetching employees
  const { adminEmployees, loading } = useSelector(
    (state) => state.adminFetchEmployeeReducer
  );
  useEffect(() => {
    dispatch(adminFetchEmployeeAction());
    if (adminEmployees === "unAuthorized") {
      navigate("/auth/true/false");
    }
  }, [adminEmployees, navigate,dispatch]);

  console.log("Here i am running infinie loop");
  console.log(adminEmployees);
  return (
    <>
      {loading ? (
        <Loader></Loader>
      ) : adminEmployees === "no employees" ? (
        <h1>No Employees</h1>
      ) : (
        <>
          {adminEmployees &&
            adminEmployees.map((employee) => {
              return (
                <div className="admin__employee__container" key={employee.id}>
                  <AdminSingleEmployee
                    employee={employee}
                  ></AdminSingleEmployee>
                </div>
              );
            })}
        </>
      )}
    </>
  );
}

Here I want to achieve 2 goals:

  1. fetch adminEmployees
  2. if (adminEmployees==='unAuthorized') then go to loginPage

but when doing this as in the code, it creates infinite loop.
How can I achieve the desired functionality?


Solution

  • Easy dirty path: split useEffect into 2

    useEffect(() => {
        if (adminEmployees === "unAuthorized") {
          navigate("/auth/true/false");
        }
      }, [adminEmployees, navigate]);
    
    useEffect(() => {
        dispatch(adminFetchEmployeeAction());
      }, [dispatch]);
    
    

    Better way: handle that case in reducer or action creator to flip flag in the store and then consume it in component:

    const { shouldNavigate } = useSelector(state => state.someSlice);
    
    useEffect(() => {
      if(shouldNavigate) {
      // flipping flag back
        dispatch(onAlreadyNavigated()));
        navigate("/yourPath...");
      },
      [navigate, dispatch, shouldNavigate]
    );