Home > front end >  enlighten me about UseEffect Loop when data not changing
enlighten me about UseEffect Loop when data not changing

Time:06-29

Hello i have this component and after some reading i have undestand that the useEffect is called again when data in array change but in my case that's not change and i get into a loop.

export default function Test() {
  
  const [dates, setDates] = useState([]);
  let values = [];
  useEffect(() => {
    getAllFilledJournauxDates().then(function(response) {
      values = response;
      setDates(values);
    }
    );
  }
  , [dates]);
    
  console.log(values);
  


  return(
    <div>
      {dates.map(date => {
        return <div>{date}</div>
      })}
    </div>
  );
}

[EDIT 2] adding the funtion getAllFilledJournauxDates()

export async function getAllFilledJournauxDates() {
    
        let dates = [];
        let journaux = getAllJournaux()
            .then(response => {
                Object.keys(response).forEach(element => {
                    dates.push(new Date(new Date(response[element].date)).getFullYear()   "-"   (new Date(response[element].date)).getMonth()   "-"   (new Date(response[element].date)).getDate());
                })
            })
        return dates;
}

[EDIT]

export default function Test() {
  
  const [dates, setDates] = useState([]);
  let values = [];
  useEffect(() => {
    console.log("useEffect"); // displayed two time in console
    getAllFilledJournauxDates().then(function(response) {
      values = response;
      setDates(values);
      console.log(values); //display the array of dates
    }
    );
  }
  , []);
    
  console.log(values); // display an empty array
  


  return(
    <div>
      {dates.map(date => {
        return <div>{date}</div> // display nothing on screen
      })}
    </div>
  );
}

Like suggered by @rowinbot i have removed the variable in array , but nothing yet on the screen, i can see that the variable is filled in my console, and the useEffect look like he is called two times ... i want to add that at first i try to fill a calendar with those values but without get the result i wanted i haved render the result most simply

CodePudding user response:

TL;DR: You should remove dates from the effect's dependency array.

Effects (a.k.a the functions we pass to the useEffect hook) on React runs after rendering, the dependency array acts as a escape hatch for running the effect in case you want to run the Effect only after certain dependencies were updated in a given render.

Here you're saying that whenever dates updates (its value changes) you want to run the Effect which in turn calls setDates(...) and mutates dates value, this produces a render of the component and since dates changed, the Effect is run once more, and... That happens indefinitely.

Just remove dates from the dependency array and you should be fine:

  useEffect(() => {
    getAllFilledJournauxDates().then(function(response) {
      values = response;
      setDates(values);
    }
    );
  }
  , []);

Just remember to keep the dependency array even if its empty, this basically tells React to only run your effect "once" (React 18' strict mode makes this a bit different on development) and prevents the loop.

Avoiding the depedency array entirely (omitting it) would result in the same outcome, an infinite loop, this tells React that on every render, you want to run the effect, which causes another render... And cycles eternally.

You can read more about Effects in the beta React docs which does a great job summarizing its semantics.

CodePudding user response:

You are updating dates inside the useEffect, and that is way on every useEffect rerun you change the dates and that causes it to rerun again and creates a loop. Try to put something else to trigger the useEffect instead of the dates. Maybe you can try to put it on change of "values" instead of dates and fetch response outside of useEffect and put it in values.

useEffect(() => {
      setDates(values);
  }
  , [values]);
    
  console.log(values);
  • Related