Passing an empty array as the second argument to useEffect makes it only run on mount and unmount, thus stopping any infinite loops.

useEffect(() => {
  setIngredients({});
}, []);

This was clarified to me in the blog post on React hooks at https://www.robinwieruch.de/react-hooks/

Answer from WhiteFluffy on Stack Overflow
Top answer
1 of 16
231

Passing an empty array as the second argument to useEffect makes it only run on mount and unmount, thus stopping any infinite loops.

useEffect(() => {
  setIngredients({});
}, []);

This was clarified to me in the blog post on React hooks at https://www.robinwieruch.de/react-hooks/

2 of 16
135

Had the same problem. I don't know why they not mention this in docs. Just want to add a little to Tobias Haugen answer.

To run in every component/parent rerender you need to use:

  useEffect(() => {

    // don't know where it can be used :/
  })

To run anything only one time after component mount(will be rendered once) you need to use:

  useEffect(() => {

    // do anything only one time if you pass empty array []
    // keep in mind, that component will be rendered one time (with default values) before we get here
  }, [] )

To run anything one time on component mount and on data/data2 change:

  const [data, setData] = useState(false)
  const [data2, setData2] = useState('default value for first render')
  useEffect(() => {

// if you pass some variable, than component will rerender after component mount one time and second time if this(in my case data or data2) is changed
// if your data is object and you want to trigger this when property of object changed, clone object like this let clone = JSON.parse(JSON.stringify(data)), change it clone.prop = 2 and setData(clone).
// if you do like this 'data.prop=2' without cloning useEffect will not be triggered, because link to data object in momory doesn't changed, even if object changed (as i understand this)
  }, [data, data2] )

How i use it most of the time:

export default function Book({id}) { 
  const [book, bookSet] = useState(false) 

  const loadBookFromServer = useCallback(async () => {
    let response = await fetch('api/book/' + id)
    response  = await response.json() 
    bookSet(response)
  }, [id]) // every time id changed, new book will be loaded

  useEffect(() => {
    loadBookFromServer()
  }, [loadBookFromServer]) // useEffect will run once and when id changes


  if (!book) return false //first render, when useEffect did't triggered yet we will return false

  return <div>{JSON.stringify(book)}</div>  
}
๐ŸŒ
DEV Community
dev.to โ€บ oyedeletemitope โ€บ three-ways-to-cause-infinite-loops-when-using-useeffect-in-react-and-how-to-prevent-them-3ip3
Three Ways to Cause Infinite Loops When Using UseEffect in React and How to Prevent Them - DEV Community
November 17, 2024 - Since there's no dependency check, the useEffect hook will also run again after the re-render. This cycle of state update triggering re-render, which in turn triggers useEffect again, will continue indefinitely, causing the infinite loop.
Discussions

useEffect causes an infinite loop?
TL;DR) Add [] as a second argument to useEffect useEffect() with no second argument will run every render. This means every time the request completes and you force a rerender by calling setItems, you will issue another request. The solution to this is the use the optional second argument to useEffect known as the dependency list. This will make it only trigger when that deps list changes. You can use an empty argument if your fetch is based on nothing []. If it changes then you can add any immutable types to that list. useEffect(() => { sanityClient .fetch( `*[_type == "issue"] | order(publishedAt desc) { title, slug, description, frontCover{ asset->{ _id, url } } }` ) .then((data) => { setItems(data); }) .catch(console.error); }, []); See the very last line that I changed above ^ See more on the official docs for useEffect https://beta.reactjs.org/reference/react/useEffect A side note, you may want to hoist your fetch method up to make it easier to read your code like so: const fetchSanity = () => sanityClient .fetch( `*[_type == "issue"] | order(publishedAt desc) { title, slug, description, frontCover{ asset->{ _id, url } } }` ) More on reddit.com
๐ŸŒ r/reactjs
16
0
January 21, 2023
Infinite loop in useEffect using blank object or array
Using React Version: 16.8.4 When using blank object or array as a setter for function inside useEffect does cause infinite loop. However using string or number does not trigger this. Here's the min... More on github.com
๐ŸŒ github.com
8
March 13, 2019
reactjs - Passing a function in the useEffect dependency array causes infinite loop - Stack Overflow
Why is an infinite loop created when I pass a function expression into the useEffect dependency array? The function expression does not alter the component state, it only references it. // componen... More on stackoverflow.com
๐ŸŒ stackoverflow.com
UseEffect Dependencies causing a infinite loop of requesting user Location
For my external UseEffect function, esLinter keeps on saying I am missing dependencies in the array for the second argument namely: [urlArray, setFunctArray, getLocationPromise, location] However as soon as I add either the urlArray, or setFunctArray . I searched and found this stackoverFlow post that says that to handle arrays in the dependency array you need to use JSON.stringify(array). This stops the infinite loop ... More on reddit.com
๐ŸŒ r/reactjs
5
0
March 12, 2023
๐ŸŒ
GitHub
github.com โ€บ facebook โ€บ react โ€บ issues โ€บ 18243
Bug: Passing an array as a `useEffect` dependency causes an infinite loop ยท Issue #18243 ยท facebook/react
March 7, 2020 - Notice in the code above, that I don't even use or modify args at all, in the useEffect callback. If I change the value of args to a string, like const args = 'a', then there is no endless loop. So the problem seems to occur when the dependency is an array. The page runs in an infinite loop.
Author ย  garyking
๐ŸŒ
Reddit
reddit.com โ€บ r/reactjs โ€บ useeffect causes an infinite loop?
r/reactjs on Reddit: useEffect causes an infinite loop?
January 21, 2023 -

Hey!! First time building a website and have ran into this issue when trying to fetch content from Sanity Studio.

Here's the link: https://pastebin.com/3iL0gpBt

Copying what I think is the relevant part of the code

export default function IssuesList() {
  const [items, setItems] = useState([]);

  useEffect(() => {
    sanityClient
      .fetch(
        `*[_type == "issue"] | order(publishedAt desc) {
      title,
      slug,
      description,
      frontCover{
        asset->{
          _id,
          url
        }
      }
    }`
      )
      .then((data) => {
        setItems(data);
      })
      .catch(console.error);
  });

  return (
    <div css={issuesListSx}>
      <Frame path={[{ name: "Issues", slug: "/issues" }]}>
        <Grid gap={2} columns={[1, null, 2]} className="issuesGrid">
          {items.map((issue) => {
            return (
              <div className="issueItem" key={issue.title}>
                <Link to={"/issues/" + issue.slug.current}>
                  <div>{issue.title}</div>
                  {issue.frontCover && "asset" in issue.frontCover && (
                    <img src={issue.frontCover.asset.url} alt="" />
                  )}
                </Link>
              </div>
            );
          })}
        </Grid>
      </Frame>
    </div>
  );
}

E: Fixed!! Had to add an empty array as a second parameter to useEffect

๐ŸŒ
LogRocket
blog.logrocket.com โ€บ home โ€บ how to solve the react useeffect hookโ€™s infinite loop patterns
How to solve the React useEffect Hook's infinite loop patterns - LogRocket Blog
June 4, 2024 - Furthermore, notice that we passed the count Hook to its dependency array as well ยท This means that every time the value of count updates, React invokes useEffect ยท As a result, the useEffect Hook invokes setCount, thus updating count again ...
๐ŸŒ
freeCodeCamp
freecodecamp.org โ€บ news โ€บ prevent-infinite-loops-when-using-useeffect-in-reactjs
How to Prevent Infinite Loops When Using useEffect() in ReactJS
April 26, 2023 - So, similar to using useEffect, we can use an empty dependency array to ensure the function isn't being re-created between renders. This prevents the effect from running in an infinite loop when a function is used as a dependency.
๐ŸŒ
Dmitri Pavlutin
dmitripavlutin.com โ€บ react-useeffect-infinite-loop
How to Solve the Infinite Loop of React.useEffect()
February 26, 2023 - The infinite loop is fixed with correct management of the useEffect(callback, dependencies) dependencies argument.
๐ŸŒ
Max Rozen
maxrozen.com โ€บ learn-useeffect-dependency-array-react-hooks
Preventing infinite re-renders when using useEffect and useState - Max Rozen
Changing state will always cause a re-render. By default, useEffect always runs after render has run. This means if you don't include a dependency array when using useEffect to fetch data, and use useState to display it, you will always trigger ...
Find elsewhere
๐ŸŒ
CodingDeft
codingdeft.com โ€บ posts โ€บ react-useeffect-infinite-loop
How to solve Infinity loop in React's useEffect | CodingDeft.com
Tutorial on how to fix infinite loop in useEffect using dependency array, useMemo, and useCallback.
๐ŸŒ
GitHub
github.com โ€บ facebook โ€บ react โ€บ issues โ€บ 15096
Infinite loop in useEffect using blank object or array ยท Issue #15096 ยท facebook/react
March 13, 2019 - function Example() { const [count, setCount] = useState(0); const [foo, setFoo] = useState({}); useEffect(() => { console.log("Infinite Loop"); setCount(100); // doesn't cause infinite loop. // but this does // setFoo({}); // or setFoo([]); }); return <div />; } I don't know if it's a bug or default behaviour because in earlier version of react (in v16.7.0-alpha.0), both string and number also causing infinite loop which seems to be fixed in latest one.
Author ย  eashish93
๐ŸŒ
DhiWise
dhiwise.com โ€บ blog โ€บ design-converter โ€บ preventing-react-useeffect-infinite-loop-simple-fixes
React UseEffect Infinite Loop: Common Causes and Solutions
March 20, 2025 - A correct dependency array ensures ... Inside the Effect: Using setState within the effect causes a re-render, which triggers the effect again, leading to an infinite loop if not controlled properly....
๐ŸŒ
Plain English
plainenglish.io โ€บ blog โ€บ 5-useeffect-infinite-loop-patterns-2dc9d45a253f
5 useEffect Infinite Loop Patterns
July 23, 2021 - To fix this issue, we need to use ... know, the shallow comparison for two is always false, so passing dependencies as an array will also lead to Infinite Loop....
๐ŸŒ
Perficient Blogs
blogs.perficient.com โ€บ 2024 โ€บ 12 โ€บ 16 โ€บ avoiding infinite loops when utilizing useeffect() in reactjs
Avoiding Infinite Loops When Utilizing useEffect() in ReactJS / Blogs / Perficient
December 16, 2024 - Even though the content of data remains the same, its reference changes with each render. As a result, the useEffect hook will be triggered on every render, leading to an infinite loop of state updates and re-renders.
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ how-to-avoid-infinite-loops-when-using-useeffect-in-reactjs
How To Avoid Infinite Loops When Using useEffect() in ReactJS? | GeeksforGeeks
October 14, 2024 - If we didn't specify any dependencies, the hook would be called after every render, causing an infinite loop. By specifying the empty array as the dependency, we ensure that the hook is only called once, and we avoid any performance issues or ...
๐ŸŒ
DEV Community
dev.to โ€บ collegewap โ€บ how-to-solve-infinity-loop-in-reacts-useeffect-5d6e
How to solve Infinity loop in React's useEffect? - DEV Community
March 28, 2023 - In the above code, we are calling setCounter inside the useEffect hook and the counter increments. As the state changes, the component gets re-rendered and useEffect runs again and the loop continues. The useEffect hook runs again as we did not pass any dependency array to it and causes an infinite loop.
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.

๐ŸŒ
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
However, its behavior is tightly ... controls when the effect runs. Mismanaging this array can lead to frustrating issues like infinite re-render loops, stale data, or unnecessary side effects....
๐ŸŒ
JavaScript in Plain English
javascript.plainenglish.io โ€บ 5-useeffect-infinite-loop-patterns-2dc9d45a253f
5 useEffect Infinite Loop Patterns | by Naveen DA | JavaScript in Plain English
July 23, 2021 - According to official docs, it ... . ... The function getData is passed as dependencies. When you run this code, it will throw Maximum update depth exceeded which means the code having an infinite loop......
๐ŸŒ
Reddit
reddit.com โ€บ r โ€บ reactjs โ€บ comments โ€บ 11pabq8 โ€บ useeffect_dependencies_causing_a_infinite_loop_of
UseEffect Dependencies causing a infinite loop of ...
March 12, 2023 - For my external UseEffect function, esLinter keeps on saying I am missing dependencies in the array for the second argument namely: [urlArray, setFunctArray, getLocationPromise, location] However as soon as I add either the urlArray, or setFunctArray . I searched and found this stackoverFlow post that says that to handle arrays in the dependency array you need to use JSON.stringify(array). This stops the infinite loop ...