Search code examples
reactjsreduxreact-hooksuse-effectredux-thunk

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?


Solution

  • 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]);