JAVASCRIPT

Optimize `useEffect` with Deep Comparison for Dependencies

Use `useDeepCompareEffect` to prevent unnecessary re-runs of `useEffect` callbacks when dependencies are complex objects or arrays, by performing a deep equality check instead of a shallow one.

import React, { useEffect, useRef } from 'react';
import isEqual from 'lodash.isequal'; // or any other deep comparison utility

const useDeepCompareEffect = (callback, dependencies) => {
  const currentDependenciesRef = useRef();

  if (!isEqual(currentDependenciesRef.current, dependencies)) {
    currentDependenciesRef.current = dependencies;
  }

  useEffect(callback, currentDependenciesRef.current);
};

// Example Usage:
// function MyDeepCompareComponent({ user }) {
//   // user might be a new object on every render even if its content is the same
//   // { id: 1, name: 'John Doe' }
//
//   useDeepCompareEffect(() => {
//     console.log('User object changed (deeply):', user);
//     // Perform some action that should only run if user's content actually changes
//   }, [user]);
//
//   useEffect(() => {
//     console.log('User object changed (shallowly):', user);
//     // This will run on every render if user is a new object reference
//   }, [user]);
//
//   return (
//     <div>
//       <p>User ID: {user.id}</p>
//       <p>User Name: {user.name}</p>
//       <p>Check console for effect logs.</p>
//     </div>
//   );
// }

// // Parent component rendering MyDeepCompareComponent
// function App() {
//   const [count, setCount] = useState(0);
//   const user = useMemo(() => ({ id: 1, name: 'John Doe', count }), [count]);
//
//   return (
//     <div>
//       <button onClick={() => setCount(count + 1)}>Increment Count ({count})</button>
//       <MyDeepCompareComponent user={user} />
//     </div>
//   );
// }
How it works: React's `useEffect` hook performs a shallow comparison of its dependency array. This means that if an object or array dependency is recreated on every render (even if its internal values are identical), the effect will re-run unnecessarily. The `useDeepCompareEffect` hook addresses this by using a deep equality comparison (e.g., `lodash.isequal`) for the dependencies. It stores the deeply compared dependencies in a `useRef` and passes that stable reference to `useEffect`, ensuring the effect only re-runs when the *actual content* of the dependencies changes. This is crucial for optimizing performance in scenarios with complex object or array dependencies.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs