简体   繁体   中英

React useEffect hook is causing infinite loop

I have an useState hook on my component, it looks like this:

const [scoutMode, setScoutMode] = useState("camp");
const [bottomLinks, setBottomLinks] = useState([]);
useEffect(() => {
if (scoutMode == "weeklyProgramme") {
  setBottomLinks([
    {
      name: "Tasks",
      link: "/tasks"
  },
  {
    name: "Checklists",
    link: "/checklists"
  }
  
  ])
} else if (scoutMode == "camp") {
  setBottomLinks([
    {
      name: "Tasks",
      link: "/tasks"
  },
  {
    name: "Map",
    link: "/map"
  }
  ])
} else {
  setBottomLinks([]);
}
console.log(bottomLinks);
})

But bottomLinks is printend on console continuously, I have an infinite loop. I remember there was a rule that useState must never be called inside useEffect, am I wrong, or could someone explain what is happening in my code?

PROBLEM:

When you modify a component's state within useEffect hook, the component will rerender causing the useEffect to be called again; thus entering into an infinite loop. That's why you should add a dependency array as a second argument to useEffect to invoke the function when dependencies change.

SOLUTION:

Add a dependency array like so:

const [scoutMode, setScoutMode] = useState("camp");
const [bottomLinks, setBottomLinks] = useState([]);
useEffect(() => {
if (scoutMode == "weeklyProgramme") {
  setBottomLinks([
    {
      name: "Tasks",
      link: "/tasks"
  },
  {
    name: "Checklists",
    link: "/checklists"
  }
  
  ])
} else if (scoutMode == "camp") {
  setBottomLinks([
    {
      name: "Tasks",
      link: "/tasks"
  },
  {
    name: "Map",
    link: "/map"
  }
  ])
} else {
  setBottomLinks([]);
}
console.log(bottomLinks);
}, [scoutMode])

you must use dependencies to useEffect function know whether rerender or not, typically syntax as

useEffect(() => {
  // code
}, [denpendencies])

In your case, if you just only it's run once, you must put dependencies by []. Otherwise, if you want useEffect run each scoutMode change, you put dependencies by [scoutMode]

  1. It first works when rendering occurs. useEffect(() => {... }, [])

  2. It works whenever the state of scoutMode changes useEffect(() => {... }, [scoutMode])

useEffect lets you perform side effects in function components. As your useEffect has state dependency( scoutMode ) and based on this, your changing the state( bottomLinks ) inside useEffect , which will cause re-render and useEffect will be called again, this goes on. That's why your seeing infinite loop. You need tell when to run the useEffect hook by adding dependancies.

In your case, you can tell useEffect to run whenever scoutMode changes by adding hook dependancy.

useEffect(() => {
 // your stuff
}, [scoutMode])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM