Search code examples
javascriptreactjsuse-effectuse-state

Async use-state infinite re-rendering


I'm creating a react js app for a project that interacts with an api. I get an array with values from the api, and those values are google maps pins. What I want to do here is: the user sets a data interval and all the pins in that data interval are shown in the map.

I have this js code to set everything:

//above is the function that receives two dates and returns the interval, not relevant here
var pinsdata = [];

  useEffect(()=>{
    axios.get('MYAPILINK')
    .then(res=>{

      var arraydatas = getDates(data1, data2)
      for(var i = 0; i < res.data.data.length; i++)
      {
        if(arraydatas.includes(res.data.data[i].data_pg))
        {
          pinsdata.push(res.data.data[i])
        }
      }
      setPorra(pinsdata)
    })
  }, [porra]) 

and for now i just have this on the return (I'm just testing this for now):

    <div>
        <DatePicker selected={startDate} onSelect={(date) => setStartDate(date)} dateFormat="dd-MM-y"/>
          &emsp;
        <DatePicker selected={startDate2} onSelect={(date2) => setStartDate2(date2)} dateFormat="dd-MM-y"/>
        <ul>
          {porra.map(pinsdata =>{
            return(<li>{pinsdata.id_pg}</li>)
          })}
        </ul>
    </div>

So... everything seems to work fine here: I set two dates and I get all the markers/pins in that data interval shown on the page.

The problem:

My page is INFINITELY re-rendering... The console.log that i have there gets spammed as soon as i refresh the page, and when i add the google map to the page, it's not even usable because the page just get's re-render every second. Now... i know that it's because of useState, but how can i get this going without use state? Because the api request is async, so i have to re-render when i have the answer from the api...


Solution

  • Try removing porra from the dependancy array and add two dates(startDate and startDate2) as the dependencies.

      useEffect(()=>{
        axios.get('MYAPILINK')
        .then(res=>{
    
          var arraydatas = getDates(data1, data2)
          for(var i = 0; i < res.data.data.length; i++)
          {
            if(arraydatas.includes(res.data.data[i].data_pg))
            {
              pinsdata.push(res.data.data[i])
            }
          }
          setPorra(pinsdata)
        })
      }, [startDate, startDate2]) 
    

    when you call setPorra inside useEffect, it creates an infinite loop.