Thursday, April 28, 2022

[FIXED] How to solve `React Hook useEffect has a missing dependency` of `react-hooks/exhaustive-deps`?

Issue

I am here to ask something about react hooks and missing dependencies.

I try to be concise, this is warning message I have in my console

Compiled with warnings.

./src/views/categories/Categories.tsx
  Line 14:6:  React Hook useEffect has a missing dependency: 'dispatcher'. Either include it or remove the dependency array  react-hooks/exhaustive-deps

the code of the hook useEffect

const [categoriesList, dispatcher] = useCategoryList({})

useEffect(() => {
  !isOpenConfirmAddModal && dispatcher.fetchCategories()
}, [isOpenConfirmAddModal])

and this is the code of the custom hook useCategoryList

export const useCategoryList = (
  initialState: CategoriesData
): CategoriesListHook => {
  const [state, dispatch] = useReducer(categoryReducer, initialState)

  const fetchCategories = async () => {
    const categories = await getCategories()
    dispatch({ type: FETCH_CATEGORIES, data: categories })
  }

  // ....

  return [
    state,
    {
      fetchCategories
      // ...
    }
  ]
}

if I set the dispatcher as dependency

useEffect(() => {
  !isOpenConfirmAddModal && dispatcher.fetchCategories()
}, [isOpenConfirmAddModal, dispatcher])

and the effect in the application is an eternal loop of call to dispatcher.fetchCategories(), it seems that dispatch is constantly updating itself and the loop is never ending.

I tried some other coouple of attempts suggested in SO, but I never saw a dispatcher from a useReducer within a useEffect.

Ideas, thanks!


Solution

In your custom hook you can not re create fetchCategories and possibly other methods using useMemo:

export const useCategoryList = initialState => {
  const [state, dispatch] = useReducer(
    categoryReducer,
    initialState
  );

  const methods = React.useMemo(
    () => ({
      fetchCategories: async () => {
        const categories = await getCategories();
        dispatch({
          type: FETCH_CATEGORIES,
          data: categories,
        });
      },
      //other methods
    }),
    []//no dependencies
  );

  return [state, methods];
};

Now fetchCategies should not change during component life cycle so you can do:

const [categoriesList, {fetchCategories}] = useCategoryList({});
useEffect(() => {
  !isOpenConfirmAddModal && fetchCategories();
}, [fetchCategories]);


Answered By - HMR
Answer Checked By - Mary Flores (PHPFixing Volunteer)

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.