Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Preventing loop inside useEffect with setState

I want to fetch data when a state value changed.

This is easy approach since I can use useEffect and tell it to run when the state value changes. something like this

useEffect(() => {
  fetch(url,(result) => {
     // this is callback function when data fetched

  });

},[value]);

and somewhere in my render, I call setValue after the user clicks a button.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

But in my situation, value has no default value so it’s undefined the first time, My API provides the initial value for value. So the first time the useEffect must set value too.

useEffect(() => {
  fetch(url,({value, ...data}) => {
     // this is callback function when data fetched
     setData(data);
     setValue(value); // <- this line make loop since value is an object
    // But I need to set value for initial value that came from server
  });

},[value]);

And this makes an infinite loop since I’m changing value on effect which depends on value.

In short

1-I get my initial value from the API call

2-I need to re-call the API after the value is changed by user click.

These 2 condition makes an infinite loop, How I can approach this?

UPDATED

The value is an object that contains a year and month and its initial value is based on the user config in the database. It’s something like {month: 10, year: 2022} and the user can change it in UI to navigate to other months.

>Solution :

I you want to fetch something when value changes, I’d rather call it once, when user changes the value object.

function fetchValue(oldValue) {
  fetch(url, ({ value, ...data }) => {
    setData(data)
    setValue(value)
  })
}

useEffect(() => {
  // initial call to the API
  fetchValue()
}, [])

// Later...
<button onClick={() => {
  const newValue = updateValue(value)
  setValue(newValue)
  fetchValue(newValue)
}} />

or if you want to centralise effect handling with useEffect, you can split user-local value from what is returned from the server:

const [userValue, setUserValue] = useState()
const [serverValue, setServerValue] = useState()

useEffect(() => {
  fetch(url, ({ value, ...data }) => {
    setServerValue(value)
    setData(data)
  })
}, [userValue])

const actualValue = serverValue || userValue

<button onClick={() => {
  setServerValue(undefined)
  setUserValue(updateValue(actualValue))
}} />
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading