Updated State doesn't trigger a re-render in React Native

Viewed 111

It's been a whole week of googling and of trial and error and I haven't still figured out what I am doing wrong.

I'm filling an AsyncStorage from an axios call with data (array of objects). Then using useEffect to update a state from the data in AsyncStorage. All of this works and the state gets updated but it doesn't trigger a render.

There are no error messages. The allData State gets updated but for some reason it doesn't trigger a re-render.

This is the state:

const [allData, setAllData] = useState([
{
  fecha_inicial: toggleSwitch.startDate,
  fecha_final: toggleSwitch.endDate,
  id_emp: 0,
  nombre_emp: '',
  ventas: {
    vta_tuno_open: '0',
    vta_dia_1: '0',
    vta_sem_0: '0',
    vta_sem_1: '0',
    vta_mes_0: '0',
    vta_mes_1: '0',
    vta_anio_0: '0',
  },
  metas: {
    dia: '0',
    semana: '0',
    mes: '0',
    año: '0',
    dia_anterior: '0',
    semana_anterior: '0',
    mes_anterior: '0',
    año_anterior: '0',
  },
},

])

This is the useEffect that fetches the data from an API and saves them into AsyncStorage:

useEffect( () => {
    const interval = setInterval( async () => {
      const empresas = await fetchAll(
        idUsuario,
        toggleSwitch.startDate,
        toggleSwitch.endDate,
      )

      storeData(empresas)
    }, 15000 )
    return () => clearInterval( interval )
  }, [] )

And this is the useEffect that updates the allData state from AsyncStorage.

  useEffect( async () => {
    const interval = setInterval( async () => {
        const dataFromAsyncStorage = await getData()
        const newData = dataFromAsyncStorage
        setAllData( newData )
        setIsLoading(false)
    }, 30000 )

    return () => clearInterval(interval)
  }, [] )

This is the render that is supposed to be updated then the "allData" state changes.

return (
        <View>
          {
            allData.map((data, index) => {
              return (
                <GaugeBar
                  key={index}
                  idEmpresa={data.id_emp}
                  title={data.nombre_emp}
                  currentValue={data.ventas.vta_tuno_open.replace(/,/g, '.')}
                  limitValue={data.metas.dia.replace(/,/g, '.')}
                  height={42}
                />
              )
            }) //END-MAP
          }
        </View>
      )

I don't need to update individual values of properties of every object inside the array of the state allData because there's no way to know which values are going to get updated. So I don't mind updating the whole thing every time.

1 Answers

The thing is that you are not passing anything to the second argument of useEffect (empty array). The documentation says that If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run.. You need to pass dependent variables e.g. newData

Related