JAVASCRIPT
React `useDeepCompareEffect` for Complex Dependency Arrays
Enhance `useEffect` by using `useDeepCompareEffect` to trigger effects only when deeply nested objects or arrays in the dependency array truly change, avoiding unnecessary re-renders.
import { useRef, useEffect } from 'react';
import isEqual from 'lodash.isequal'; // or a custom deep comparison function
function useDeepCompareEffect(callback, dependencies) {
const currentDependenciesRef = useRef(dependencies);
if (!isEqual(currentDependenciesRef.current, dependencies)) {
currentDependenciesRef.current = dependencies;
}
useEffect(callback, currentDependenciesRef.current);
}
// Example of a custom isEqual if lodash is not desired:
/*
function deepCompare(a, b) {
if (a === b) return true;
if (a == null || typeof a != 'object' || b == null || typeof b != 'object') return false;
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) return false;
for (let i = 0; i < keysA.length; i++) {
const key = keysA[i];
if (!keysB.includes(key) || !deepCompare(a[key], b[key])) {
return false;
}
}
return true;
}
*/
How it works: The standard `useEffect` hook performs a shallow comparison of its dependency array. When dependencies are complex objects or arrays, this can lead to effects firing too often (if a new object reference is created on every render, even if its content is the same) or not often enough (if the object content changes but its reference doesn't). `useDeepCompareEffect` addresses this by using a deep comparison (here, `lodash.isequal` is suggested) to determine if dependencies have truly changed, thereby optimizing effect execution.