Passing stateful objects to the useEffect is fine? If it’s coming from redux the only time the reference would change is dispatching an action that would change them. The only problem with passing non primitives to useEffects is when you create them during the render, making the reference unstable Answer from RobKnight_ on reddit.com
🌐
Reddit
reddit.com › r/reactjs › what if you need to check an object in the useeffect dependency array?
r/reactjs on Reddit: What if you need to check an object in the useEffect dependency array?
August 2, 2023 -

I have an object that looks something like this stored in a Redux store:

[ layer1: false, layer2: true, layer3: false]

These flags represent layers that are shown or hidden on a Leaflet map.

The various fields are toggled by their associated inputs and in the component which consumes them, I need to add or remove the specified layers when the object above changes.

Since you can't pass non-primitives into the useEffect dependency array, I considered trying the following I found on SO:

useEffect(() => {

// ...

), [JSON.stringify(myLayersObject)])

This doesn't work, I think because it's effectively passing a constant in the dependency list.

I am also considering using a byte to store the flags and doing bitwise manipulation to check the values. That should work, but it may be somewhat unclear to other devs what I am doing, so any alternative suggestions are welcome.

The usual remedy of trying to extract only the primitive property you care about doesn't work, because i need to care about all of them. In the real code there are only layers, and I suppose I could make 6 useEffect hooks with dependency arrays like [myLayersObject.layer1], etc. but that is also ugly.

Any suggestions?

Thanks.

🌐
Profy.dev
profy.dev › article › react-useeffect-with-object-dependency
React useEffect and objects as dependency - 4 approaches to avoid unnecessary re-renders
March 19, 2024 - Let's give it a try. First, we install the dependency. ... Then, we replace the useEffect with a new useDeepCompareEffect hook. We can now simply pass the filters object as a dependency, and the effect won't be run on every render anymore.
People also ask

Why is the dependency array important in useEffect?
The dependency array in useEffect tells React when to re-run the effect. It ensures the effect only runs when specified state or prop values change, improving performance and avoiding unnecessary renders.
🌐
dhiwise.com
dhiwise.com › post › understanding-the-importance-of-the-useeffect-dependency-array-in-react
UseEffect Dependency Array: Best Practices For React ...
Can you use objects or arrays in the useEffect dependency array?
Yes, but JavaScript compares object or array references, not their contents. This can cause unnecessary re-renders. To avoid this, use the useMemo hook to memoize objects or arrays used in the dependency array.
🌐
dhiwise.com
dhiwise.com › post › understanding-the-importance-of-the-useeffect-dependency-array-in-react
UseEffect Dependency Array: Best Practices For React ...
What happens if you don’t pass a dependency array to useEffect?
Without a dependency array, the effect runs after every render. This can lead to performance issues and bugs since the effect won't re-run based on changes in specific dependencies.
🌐
dhiwise.com
dhiwise.com › post › understanding-the-importance-of-the-useeffect-dependency-array-in-react
UseEffect Dependency Array: Best Practices For React ...
🌐
React
react.dev › reference › react › useEffect
useEffect – React
See the difference between passing an array of dependencies, an empty array, and no dependencies at all. ... useEffect is a Hook, so you can only call it at the top level of your component or your own Hooks.
Top answer
1 of 7
115

Use apiOptions as state value

I'm not sure how you are consuming the custom hook but making apiOptions a state value by using useState should work just fine. This way you can serve it to your custom hook as a state value like so:

const [apiOptions, setApiOptions] = useState({ a: 1 })
const { data } = useExample(apiOptions)

This way it's going to change only when you use setApiOptions.

Example #1

import { useState, useEffect } from 'react';

const useExample = (apiOptions) => {
  const [data, updateData] = useState([]);
  
  useEffect(() => {
    console.log('effect triggered')
  }, [apiOptions]);

  return {
    data
  };
}
export default function App() {
  const [apiOptions, setApiOptions] = useState({ a: 1 })
  const { data } = useExample(apiOptions);
  const [somethingElse, setSomethingElse] = useState('default state')

  return <div>
    <button onClick={() => { setApiOptions({ a: 1 }) }}>change apiOptions</button>
    <button onClick={() => { setSomethingElse('state') }}>
      change something else to force rerender
    </button>
  </div>;
}

Alternatively

You could write a deep comparable useEffect as described here:

function deepCompareEquals(a, b){
  // TODO: implement deep comparison here
  // something like lodash
  // return _.isEqual(a, b);
}

function useDeepCompareMemoize(value) {
  const ref = useRef() 
  // it can be done by using useMemo as well
  // but useRef is rather cleaner and easier

  if (!deepCompareEquals(value, ref.current)) {
    ref.current = value
  }

  return ref.current
}

function useDeepCompareEffect(callback, dependencies) {
  useEffect(
    callback,
    dependencies.map(useDeepCompareMemoize)
  )
}

You can use it like you'd use useEffect.

2 of 7
30

If the input is shallow enough that you think deep equality would still be fast, consider using JSON.stringify:

const useExample = (apiOptions) => {
    const [data, updateData] = useState([]);
    const apiOptionsJsonString = JSON.stringify(apiOptions);

    useEffect(() => {
       const apiOptionsObject = JSON.parse(apiOptionsJsonString);
       doSomethingCool(apiOptionsObject).then(response => {               
           updateData(response.data);
       })
    }, [apiOptionsJsonString]);

    return {
        data
    };
};

Note it won’t compare functions.

🌐
Ben Ilegbodu
benmvp.com › blog › object-array-dependencies-react-useEffect-hook
Object & array dependencies in the React useEffect Hook | Ben Ilegbodu
January 2, 2021 - React checks to see if the object in the current render points to the same object in the previous render. The objects have to be the exact same object in order for useEffect to skip running the effect.
🌐
DEV Community
dev.to › hey_yogini › useeffect-dependency-array-and-object-comparison-45el
UseEffect dependency array and object comparison! - DEV Community
January 5, 2022 - In my opinion the real take-away for an article with a topic like yours should be: a) just go for it and put all props you depend on in the dependency array, or b) stringify the object you're depending on (might be slow and unreliable) or c) utilize an external library like github.com/kentcdodds/use-deep-com... or write a custom useEffect hook yourself - it's basically just comparing the previous version of an object (stored via useRef()) with the current one, it's no magic
Find elsewhere
🌐
Untitled Publication
haybeecodes.hashnode.dev › having-objects-as-dependencies-in-react-useeffect-hook
Having objects as dependencies in React useEffect hook
August 17, 2022 - What it does is to check for changes in any of the values that’s in the dependencies array and based on this , cause a rerender or not . So in our very first counter example where the count is stored as a primitive value and not an object, React checks if count is same between the current and previous time the useEffect hook ran .
🌐
Retool
retool.com › blog › hooks-and-state-102-the-dependency-array-in-useeffect
Retool Blog | Hooks and state 102: the Dependency array in useEffect()
July 9, 2025 - So even if the contents are the ... the effect. If you have an object or array as a dependency of useEffect, and then update that object inside the effect, you effectively create a new object with a new reference .....
🌐
Reddit
reddit.com › r/reactjs › react useeffect and objects as dependency - 4 approaches to avoid unnecessary re-renders
r/reactjs on Reddit: React useEffect and objects as dependency - 4 approaches to avoid unnecessary re-renders
March 22, 2024 - Yes, you will still have to employee strategy 2 (which is the only objectively correct strategy) in your useMemo dependencies, but that will allow you to contain the complexity of the object in a separate place to make it a stable dependency. If you know the properties of the object in the same code as the useEffect then you could just use strategy 2 every time.
🌐
DhiWise
dhiwise.com › post › understanding-the-importance-of-the-useeffect-dependency-array-in-react
UseEffect Dependency Array: Best Practices For React ...
August 13, 2025 - React applications can behave unpredictably when effects trigger at the wrong time. A harmless change can suddenly create an endless render loop, or a missing dependency warning can break your focus. What determines the exact moment an effect should run? Often, the answer lies in the useEffect dependency array.
🌐
Medium
medium.com › @joabi › react-patterns-optimization-of-dependency-array-in-useeffect-b551d172fc76
React Patterns: Optimization of Dependency Array in useEffect | by Julie J. | Medium
November 4, 2023 - This is because React uses a concept called “referential equality” when it comes to objects in the dependency array. What this means is that we can’t be sure if the object’s reference will remain the same between re-renders. So, even if the content inside the object hasn’t changed, React may still think it’s a different object and trigger the effect to run again. Our goal should be to reduce how often the object’s reference changes. import { useEffect, useState } from "react"; function Expense(props) { useEffect(() => { console.log("Run effect when date changed"); }, [props.date]
🌐
Medium
medium.com › @vishalthakur2463 › what-kind-of-values-does-the-useeffect-dependency-array-accept-c443738107c7
What Kind of Values Does the useEffect Dependency Array Accept? | by Vishal Solanki | Medium
September 20, 2025 - The dependency array in useEffect can accept any type of JavaScript value. These include: Primitives: Numbers, strings, Booleans, null, and undefined. Objects: Arrays, plain objects, dates, and more complex data structures.
🌐
Medium
medium.com › suyeonme › react-lets-deep-dive-into-deps-array-of-useeffect-13ab96468db7
React: Let’s deep dive into deps array of useEffect | by Suyeon Kang | suyeonme | Medium
July 31, 2022 - If we want to run useEffect based on the object(reference type), we should compare dependencies with deep equal.
🌐
React
react.dev › learn › removing-effect-dependencies
Removing Effect Dependencies – React
Now that options is declared inside of your Effect, it is no longer a dependency of your Effect. Instead, the only reactive value used by your Effect is roomId. Since roomId is not an object or function, you can be sure that it won’t be ...
🌐
DEV Community
dev.to › vasughanta09 › the-react-useeffect-object-dependency-trap-how-cloudflare-accidentally-ddosed-itself-2ge6
The React useEffect Object Dependency Trap: How Cloudflare Accidentally DDoSed Itself - DEV Community
February 2, 2026 - The useEffect dependency array isn't inherently broken—it's doing exactly what it was designed to do: detect changes via reference equality. The problem arises when developers (understandably) expect value equality for objects.
🌐
Kinsta®
kinsta.com › home › resource center › blog › react errors › how to fix the “react hook useeffect has a missing dependency” error
How To Fix the “React Hook useEffect Has a Missing Dependency” Error
October 1, 2025 - In a situation where a variable that the effect depends on is not included in the dependency array, the effect may not be re-executed when the value changes. This can lead to unexpected behavior and bugs in your application.
🌐
React
react.wiki › home › react hooks › useeffect dependency array: deep mechanics explained
useEffect Dependency Array: Deep Mechanics Explained | react.wiki
January 1, 2026 - When you define a function inside the component and use it in an effect, React creates a new function object every render: ... function SearchResults() { const [results, setResults] = useState([]); function performSearch(query: string) { return fetch(`/api/search?q=${query}`).then(r => r.json()); } useEffect(() => { performSearch('react'); // ❌ PROBLEM: performSearch is recreated every render // If you add it as dependency, effect runs every render }, [performSearch]); // ← Infinite loop!
🌐
egghead.io
egghead.io › lessons › react-handle-deep-object-comparison-in-react-s-useeffect-hook-with-the-useref-hook
Handle Deep Object Comparison in React's useEffect hook with the useRef Hook | egghead.io
The second argument to React's useEffect hook is an array of dependencies for your useEffect callback. When any value in that array changes, the effect callback is re-run. But the variables object we're passing to that array is created during ...
Published   November 29, 2018