reactjscallbackresizedebouncingreact-usememo

Dependencies array issue with useMemo and a debounced function


I have the following code that uses lodash.debounce:

// Get Dimensions
// Capture dimensions when `App` first mounts, immediately
// Listen for resize events and trigger 'getDimensions' (debounced)
const getDimensions = () => dispatch(setDimensions({
    viewportWidth: window.innerWidth,
    viewportHeight: window.innerHeight
}))

const handleResize = useMemo(() =>
    debounce(getDimensions, 250)
, [getDimensions])

useEffect(() => {
    handleResize()
    window.addEventListener('resize', handleResize)
})

While this appears to work, and I can observe on Redux DevTools that my debounced function is successfully being triggered at the right time, I get a react-hooks/exhaustive-deps error on Terminal:

The 'getDimensions' function makes the dependencies of useMemo Hook (at line 45) change on every render. Move it inside the useMemo callback. Alternatively, wrap the definition of 'getDimensions' in its own useCallback() Hook

If I remove getDimensions and the entire dependency array from handleResize, it still works BUT I get this error instead:

React Hook useMemo does nothing when called with only one argument. Did you forget to pass an array of dependencies?

I'm a bit confused on the dependency array. From a logic point of view, to my understanding, I don't want a dependency array there - or I want an empty one (which also works!) - can someone help me understand why I am getting this error and what I can do to improve my code so it's clean with no errors?


Solution

  • Add fixes for whatever the linting is warning about,

     // Get Dimensions
      // Capture dimensions when `App` first mounts, immediately
      // Listen for resize events and trigger 'getDimensions' (debounced)
      const getDimensions = useCallback(
        () =>
          dispatch(
            setDimensions({
              viewportWidth: window.innerWidth,
              viewportHeight: window.innerHeight
            })
          ),
        [dispatch]
      );
    
      const handleResize = useMemo(() => debounce(getDimensions, 250), [
        getDimensions
      ]);
    

    useCallback will return a new reference if any of the introduced values/dependecies array values changes. useMemo based on the getDimensions version( It compares between previous and latest dependencies) calculates result,allows for re-rendering.