You can pass JSON.stringify(outcomes) as the dependency list:

Read more here

useEffect(() => {
  console.log(outcomes)
}, [JSON.stringify(outcomes)])
Answer from Loi Nguyen Huynh on Stack Overflow
Top answer
1 of 7
195

You can pass JSON.stringify(outcomes) as the dependency list:

Read more here

useEffect(() => {
  console.log(outcomes)
}, [JSON.stringify(outcomes)])
2 of 7
23

Using JSON.stringify() or any deep comparison methods may be inefficient, if you know ahead the shape of the object, you can write your own effect hook that triggers the callback based on the result of your custom equality function.

useEffect works by checking if each value in the dependency array is the same instance with the one in the previous render and executes the callback if one of them is not. So we just need to keep the instance of the data we're interested in using useRef and only assign a new one if the custom equality check return false to trigger the effect.

function arrayEqual(a1: any[], a2: any[]) {
  if (a1.length !== a2.length) return false;
  for (let i = 0; i < a1.length; i++) {
    if (a1[i] !== a2[i]) {
      return false;
    }
  }
  return true;
}

type MaybeCleanUpFn = void | (() => void);

function useNumberArrayEffect(cb: () => MaybeCleanUpFn, deps: number[]) {
  const ref = useRef<number[]>(deps);

  if (!arrayEqual(deps, ref.current)) {
    ref.current = deps;
  }

  useEffect(cb, [ref.current]);
}

Usage

function Child({ arr }: { arr: number[] }) {
  useNumberArrayEffect(() => {
    console.log("run effect", JSON.stringify(arr));
  }, arr);

  return <pre>{JSON.stringify(arr)}</pre>;
}

Taking one step further, we can also reuse the hook by creating an effect hook that accepts a custom equality function.

type MaybeCleanUpFn = void | (() => void);
type EqualityFn = (a: DependencyList, b: DependencyList) => boolean;

function useCustomEffect(
  cb: () => MaybeCleanUpFn,
  deps: DependencyList,
  equal?: EqualityFn
) {
  const ref = useRef<DependencyList>(deps);

  if (!equal || !equal(deps, ref.current)) {
    ref.current = deps;
  }

  useEffect(cb, [ref.current]);
}

Usage

useCustomEffect(
  () => {
    console.log("run custom effect", JSON.stringify(arr));
  },
  [arr],
  (a, b) => arrayEqual(a[0], b[0])
);

Live Demo

🌐
React
react.dev › reference › react › useEffect
useEffect – React
The list of dependencies must have a constant number of items and be written inline like [dep1, dep2, dep3]. React will compare each dependency with its previous value using the Object.is comparison.
Discussions

Passing an array as dependency for useEffect in React
So… I need my effect to hit everytime an array im passing as dependency gets altered. I quickly realized it causes an infinite loop. I searched and searched and the one person on suggested passing [array.lenght] as the dependency and it ACTUALLY worked… but… its glitchy… looks VERY ... More on forum.freecodecamp.org
🌐 forum.freecodecamp.org
1
0
April 8, 2022
reactjs - How to manage dependency arrays with useEffect - Stack Overflow
If I do this REACT will throw a ... missing dependenecy, varA and ask that it be added to the array. But doing so will create behavior I do not want. How can I handle the warning in this situation? ... Ignore the warning. You are correct in your thinking. You do not need the other variable ... One of the rules of React hooks is that useEffect must include ... More on stackoverflow.com
🌐 stackoverflow.com
You can't use objects or arrays in useEffect?
State variables are "memorized" between renders (same as refs*) so you can use them. Arrays and objects, as you correctly understood, will be compared by reference so you have to memorize them (ref, state or useMemo). Though there is an alternative options (more so for objects than arrays but for "tuple arrays" it could still make sense) that you just add it to the dependency array in a destructed fashion. You might even find that you don't need all fields, just some. *Just remember that useEffect is tied to renders and changing a ref does not guarantee a re-render so it also does not guarantee a re-run of the useEffect even if you include it into the dependency array (it will run but only after something else triggers the render). More on reddit.com
🌐 r/reactjs
16
1
November 5, 2023
reactjs - Passing a function in the useEffect dependency array causes infinite loop - Stack Overflow
Bring the best of human thought and AI automation together at your work. Explore Stack Internal ... Why is an infinite loop created when I pass a function expression into the useEffect dependency array? More on stackoverflow.com
🌐 stackoverflow.com
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
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
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
🌐
Reddit
reddit.com › r/reactjs › passing array to useeffect dependency list
r/reactjs on Reddit: Passing array to useEffect dependency list
August 21, 2019 -

I'm having an issue with useEffect not firing if an array in the dependency list changes.

//props.shapes = ['stuff', 'in', 'the', 'array']
useEffect(() => {
   // do stuff
  }, [props.shapes])

Nothing in that useEffect runs. This...should work right? If the array changes higher up in the component tree a new array is generated and that should trigger a re-render in this component and then the useEffect will fire, right?

What's weird is if I make it dependent on the length, it does work

//props.shapes = ['stuff', 'in', 'the', 'array']
useEffect(() => {
   // do stuff
  }, [props.shapes.length])

My gut tells me that this array is actually getting mutated somewhere and that is causing the issue...but I don't see that in the app. What am I fundamentally misunderstanding about arrays (and I guess objects) with useEffect?

Ninja Edit: I know that using .length in the array dependency will lead to bugs if the array values change but the length doesn't. I don't plan on using this, just explaining what I'm experiencing.

🌐
DhiWise
dhiwise.com › post › understanding-the-importance-of-the-useeffect-dependency-array-in-react
UseEffect Dependency Array
August 13, 2025 - This blog provides a clear, structured ... strategies to help your components work as intended. The dependency array is the second parameter you pass to the useEffect hook....
🌐
Retool
retool.com › blog › hooks-and-state-102-the-dependency-array-in-useeffect
Hooks and state 102: the Dependency array in useEffect()
July 9, 2025 - The correct solution here is to use `isDesktop` and `selectedPatient` to initialize component state variables. Whenever `selectedPatient` changes, the first useEffect will update both states with the passed-in props, ...
Find elsewhere
🌐
Medium
medium.com › devil-is-in-the-details › dependency-array-in-useeffect-hook-d73e0ef2ab33
Dependency array in useEffect hook | by Shreejit Rajbanshi | Devil is in the Details | Medium
November 20, 2022 - This might be the most common form used with useEffect. We pass an array filled with all the dependencies that should trigger the callback function to run. Change in any of the variable in the list will execute the callback.
🌐
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]
🌐
Zipy
zipy.ai › blog › react-useeffect-dependency-array
React useEffect Dependency Array Guide
May 23, 2024 - The component's state can be updated or side effects can be carried out using this function. Passing an empty array as the dependent parameter for the useEffect hook in React is one of the easiest ways to use it.
🌐
GitHub
gist.github.com › msubhan9803 › 8a8e4fe91628635c6c84c627affa16d1
Passing array to useEffect dependency list · GitHub
Passing array to useEffect dependency list. GitHub Gist: instantly share code, notes, and snippets.
🌐
egghead.io
egghead.io › lessons › react-manage-the-useeffect-dependency-array
Manage the useEffect dependency array | egghead.io
[0:54] React useEffect accepts a second argument as an optimization to combat this problem. That second argument is a dependency array where you pass all the dependencies for your side effect.
Published   March 10, 2020
🌐
Bitstack
blog.bitsrc.io › understanding-dependencies-in-useeffect-7afd4df37c96
Understanding Dependencies in useEffect | Bits and Pieces
March 4, 2025 - Now what about the dependency array passed to useEffect? We know from the documentation that: It’s optional. If you don’t specify it, the effect runs after each render. If it’s empty ([]), the effect runs once, after the initial render. It must — or as we’ll see later, should — contain the list ...
🌐
YouTube
youtube.com › shorts › qADQdrEKuJw
Mastering useEffects: Arrays and Objects as Dependencies - YouTube
JavaScript Arrays and Objects within React dependency arrays can be really tricky. Let's see how adding a little more specificity to our dependency arrays ca...
Published   February 1, 2023
🌐
The Web Dev
thewebdev.info › home › how to pass an array to useeffect dependency list in react?
How to pass an array to useEffect dependency list in React? - The Web Dev
November 14, 2021 - To pass an array to useEffect dependency list in React, we can pass in the array state into the dependencies list.
🌐
Ben Ilegbodu
benmvp.com › blog › object-array-dependencies-react-useEffect-hook
Object & array dependencies in the React useEffect Hook | Ben Ilegbodu
January 2, 2021 - I've already discussed dealing ... post I want to focus on options we have when dealing with objects or arrays as useEffect dependencies. In this first problem, let's say we have an object being passed in as a prop that we're also using in the dependencies list of ...
🌐
CodeSandbox
codesandbox.io › s › 59467758passing-array-to-useeffect-dependency-list-m5ho7
59467758/passing-array-to-useeffect-dependency-list - CodeSandbox
March 16, 2021 - 59467758/passing-array-to-useeffect-dependency-list by NearHuscarl using react, react-dom, react-scripts
Published   Mar 16, 2021
Author   NearHuscarl
🌐
w3tutorials
w3tutorials.net › blog › passing-array-to-useeffect-dependency-list
React useEffect Array Dependency: How to Avoid Infinite Loops and Dispatch Actions on Changes — w3tutorials.net
Mismanaging this array can lead to frustrating issues like infinite re-render loops, stale data, or unnecessary side effects. In this blog, we’ll demystify the useEffect dependency array, explore why infinite loops occur, and learn how to safely dispatch actions (e.g., Redux, Context API) when dependencies change.
🌐
Reddit
reddit.com › r/reactjs › you can't use objects or arrays in useeffect?
r/reactjs on Reddit: You can't use objects or arrays in useEffect?
November 5, 2023 -

Specifically, inside the dependency array. I've scoured the docs to find an answer to this question but couldn't find anything. Even read Dan Abramov's long guide to useEffect and still couldn't figure it out.

Is it true that, since 1) rerenders recreate objects/arrays that are declared inside your component 2) the dependency array compares objects by reference, not by value, that if you put an object inside a useEffect dependency array it'll run every time?

If so, what about if I memoize the object with useMemo? Also, what about state variables? Does React check a useState value differently than if you declare something inside the component?

If anyone can help me understand this better, even if it's just linking to a specific part of the docs, I'd appreciate it a lot.

Top answer
1 of 3
112

The issue is that upon each render cycle, markup is redefined. React uses shallow object comparison to determine if a value updated or not. Each render cycle markup has a different reference. You can use useCallback to memoize the function though so the reference is stable. Do you have the react hook rules enabled for your linter? If you did then it would likely flag it, tell you why, and make this suggestion to resolve the reference issue.

const markup = useCallback(
  (count) => {
    const stringCountCorrection = count + 1;
    return (
      // Some markup that references the sections prop
    );
  },
  [/* any dependencies the react linter suggests */]
);

// No infinite looping, markup reference is stable/memoized
useEffect(() => {
  if (sections.length) {
    const sectionsWithMarkup = sections.map((section, index) => markup(index));
    setSectionBlocks(blocks => [...blocks, ...sectionsWithMarkup]);
  } else {
    setSectionBlocks([]);
  }
}, [sections, markup]);

Alternatively if the markup function is only used in the useEffect hook you can move it directly into the hook callback to remove it as an external dependency for the hook.

Example:

useEffect(() => {
  const markup = (count) => {
    const stringCountCorrection = count + 1;
    return (
      // Some markup that references the sections prop
    );
  };

  if (sections.length) {
    const sectionsWithMarkup = sections.map((section, index) => markup(index));
    setSectionBlocks(blocks => [...blocks, ...sectionsWithMarkup]);
  } else {
    setSectionBlocks([]);
  }
}, [sections, /* any other dependencies the react linter suggests */]);

Additionally, if the markup function has absolutely no external dependencies, i.e. it is a pure function, then it could/should be declared outside any React component.

2 of 3
9

Why is an infinite loop created when I pass a function expression

The "infinite loop" is the component re-rendering over and over because the markup function is a NEW function reference (pointer in memory) each time the component renders and useEffect triggers the re-render because it's a dependency.

The solution is as @drew-reese pointed out, use the useCallback hook to define your markup function.