Proper understanding of dependency array in useEffect when working with Redux Thunk

I am starting to learn Redux and the thunk library.

I have an Actions.js which holds the function:

export const fetchInventory = (user_id) => {
return (dispatch) => {
    dispatch(fetchInventoryData());
    fetch("url", {
      method: "POST",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },

      //make sure to serialize your JSON body
      body: JSON.stringify({ user_id }),
    })
      .then((res) => res.json())
      .then((res) => {
        saveInventory(res);
        dispatch(fetchInventorySuccess(res));
      })
      .catch((err) => dispatch(fetchInventoryFailure(err)));
  };
};

and a Container.js with the useEffect as follows:

  useEffect(() => {
    if (inventory.inventoryData.length > 0) return;
    else if (user_id) fetchInventory(user_id);
    else return [];
  }, [user_id]);

EsLint gives me a warning that I am missing fetchInventory and inventory in the dependency array. However, since inventory is the state that this fetch will update, including it throws us into an infinite fetch. Also, the user_id necessary here is something that comes from a fetch request prior to this one. In a situation like this, what would go into the dependency array and why?

Answer

inventory should certainly be included in the dependency array since it is referenced in the hook callback (and likely also the fetchInventory action creator, for the same reason).

I believe the issue here is an improper guard clause (i.e. condition) for which you are calling the callback that updates state (and dependency).

The if-else-if-else is the issue. when the first condition fails, because inventory.inventoryData.length is non-zero, the second condition is checked, and sure enough there’s a defined user_id value and the callback is invoked.

From what I can gather, the condition you want is “if there is no inventory data AND there is a user id, then fetch inventory, otherwise do nothing”.

Try simplifying your condition and branching factor.

useEffect(() => {
  if (!inventory.inventoryData.length && user_id) {
    fetchInventory(user_id)
  }
}, [fetchInventory, inventory.inventoryData, user_id]);