I have a custom hook that is responsible for fetching some user-related data from my backend on app initialization and storing it in global state that is required by multiple components. The data-fetching is triggered from a useEffect
inside of the hook, and since multiple components (that are rendered in the same view) are all calling the hook to access the data, said useEffect
is firing multiple times, hence the API is called as many times as the hook is called.
Here is a simplified version of what's going on inside of the custom hook:
const useMyCustomHook = () => {
const [user] = useAuthState(auth); // hook for accessing firebase user
const [data, setData] = useRecoilState([]); // using Recoil state-management lib for global state
useEffect(() => {
if (!user || data.length) return;
const fetchData = async () => {
const apiData = await APICall(someAPIURL);
setData(apiData);
};
}, [user, data]);
return { data };
};
This data is access in several components via:
const { data } = useMyCustomHook();
So basically the if
statement inside of the useEffect
protects against API calls if the data is in state, however, since on initialization, the useEffect
is firing multiple times (since the components calling it are on the screen at the same time), each triggering an async
call that hasn't finished before the other components trigger the same effect, therefore the API is called multiple times since state has not yet been populated by the preceding call.
What would be a way to avoid this? Is there a way to let the other components using the hook know that the initial API fetch is 'inProgress' or something?
Any advice is appreciated. Thank you very much.