0

I'm trying to do the following code but the linting is warning me to add the employeesApi to the dependency array in the useEffect. The problem is that it enters in an infinite loop and keeps executing the API request if I add the employeesApi to the dependency array

export const EmployeesListPage = () => {
    const navigate = useNavigate();

    const [employees, setEmployees] = useState<EmployeeListDto[]>([]);

    const employeesApi = useApi(new EmployeesApi());

    useEffect(() => {
        async function getEmployeesList() {
            const employeesList = await employeesApi.getEmployeesList();
            setEmployees(employeesList);
        }

        getEmployeesList();
    }, []);

    return (...)
}

EDIT:

I found the solution using an article suggested by Bikas Lin

Turns out that I read some of the react articles as well and I found out that my custom hook would always be executed at every render.

and because of that, my useAPI was executed at every render and as a parameter, I was sending a new instance of my EmployeesApi at every render.

This makes the dependency array comparison crazy as react does a comparison with objects by its reference (different from a primitive value). So at every render the reference for the EmployeesApi would be a new one and that would trigger the useEffect.

I fixed by tweaking my useApi hook to use a STATE for the API and I'm now instantiating the API inside my custom hook like so:

export const useApi = <T extends IApi>(ApiType: new () => T): T => {
    const { loggedUser } = useUserManagement();
    const [api] = useState<T>(new ApiType());

    api.setUser(loggedUser);

    return api;
};

and now I can use it perfectly in my component because the reference will always be the same

export const EmployeesListPage = () => {
    const navigate = useNavigate();

    const [employees, setEmployees] = useState<EmployeeListDto[]>([]);

    const employeesApi = useApi(EmployeesApi);

    useEffect(() => {
        async function getEmployeesList() {
            const employeesList = await employeesApi.getEmployeesList();
            setEmployees(employeesList);
        }

        getEmployeesList();
    }, [employeesApi]);

    return (...)
}
gabriel.santos
  • 160
  • 1
  • 10
  • What is the content of the `useApi` hook? – CertainPerformance Nov 08 '22 at 01:13
  • It creates a structure to use my APIs passing the token that is stored in a Context. Inside the useApi, I call the useContext passing my userManagementContext (where I can find the logged user and its token for the APIs) – gabriel.santos Nov 08 '22 at 01:17
  • I don't see any problem, other than you ignoring the tool that is telling you that your code is most likely wrong. You don't want to just add that to the dependency array because....? – Jared Smith Nov 08 '22 at 01:17
  • But what's wrong with keeping it in the dep array? – kind user Nov 08 '22 at 01:17
  • You can just add `// eslint-disable-next-line react-hooks/exhaustive-deps` to disable that lint. – Bikas Lin Nov 08 '22 at 01:18
  • 1
    @BikasLin and the point of doing so would be? Again, that lint rule *exists for a reason*, because it is almost always right. If you're going to tell the linter to shut up when it tells you your code is wrong, why bother using it at all? – Jared Smith Nov 08 '22 at 01:19
  • @kinduser it enters in an infinite loop and keeps executing the API request – gabriel.santos Nov 08 '22 at 01:20
  • @BikasLin not an option because I was planning to use this approach in lots of places in the system. Don't want to add a linting ignore line on every call – gabriel.santos Nov 08 '22 at 01:21
  • 1
    @gabriel.santos that would be pertinent information for the question itself. Did you expect us to magically intuit that was happening? We don't have access to all of the code. Please create a complete minimal reproduction case in the question itself including all relevant data, per the [help center](https://stackoverflow.com/help/how-to-ask). – Jared Smith Nov 08 '22 at 01:21
  • @JaredSmith I did write it all but the page bugged and didn't save my edit. I saw that just now – gabriel.santos Nov 08 '22 at 01:23
  • @gabriel.santos downvote removed. If `.getEmployeesList()` modifies employeesApi that could certainly happen, but I'm guessing it's because you need to also include a conditional check to see if employees has already been set in your effect hook. – Jared Smith Nov 08 '22 at 01:28
  • @gabriel.santos Adding `// eslint-disable-next-line react-hooks/exhaustive-deps` only affects the only following line, not whole codes. – Bikas Lin Nov 08 '22 at 01:30
  • @JaredSmith I can understand what you are saying. But sometimes, we don't need to, should not pass any dependencies. – Bikas Lin Nov 08 '22 at 01:32
  • @BikasLin I know that, but I would need to add this //eslint-disable-next-line several times in my code. My CodeSens is screaming my problem is structural. But as I'm new to react idk how to solve it. I just need a good structure to deal with API Calls using my logged user token. Any suggestion on a good API structure using axios would be appreciated – gabriel.santos Nov 08 '22 at 01:49
  • 1
    @gabriel.santos https://javascript.plainenglish.io/custom-hook-in-react-js-for-calling-api-useapi-7de24b42729c. Is this helpful for you? – Bikas Lin Nov 08 '22 at 02:01
  • @BikasLin this was helpful as I could get some ideas from the article and solved my problem. You cans see in my edit. Thank you – gabriel.santos Nov 08 '22 at 23:43

0 Answers0