Home > Net >  React Native components don't update as soon as they calculate
React Native components don't update as soon as they calculate

Time:03-29

I have a list of components in a screen. Each component makes a calculation on useEffect. I expect then to update as soon as they finish each calculation, but instead they all update after all calculations completes.

What I'm doing wrong?

Example of component:

import React, {useEffect, useState} from 'react';
import {View, Text} from 'react-native';

const Teste = () => {
  const Item = props => {
    const [tempo, setTempo] = useState('calculando...');

    useEffect(() => {
      const inicio = new Date();
      const rdm = Math.random();
      sleep(rdm * 1000   2000);
      setTempo(`${new Date() - inicio} millisegundos`);
    }, []);

    const sleep = milliseconds => {
      const date = Date.now();
      let currentDate = null;
      do {
        currentDate = Date.now();
      } while (currentDate - date < milliseconds);
    };

    return (
      <View style={{marginBottom: 20}}>
        <Text>Item {props.nome}</Text>
        <Text>Tempo - {tempo}</Text>
      </View>
    );
  };

  return (
    <View style={{padding: 40}}>
      <Item nome="1" />
      <Item nome="2" />
      <Item nome="3" />
    </View>
  );
};

export default Teste;

CodePudding user response:

Two problems here...

  1. That sleep function, I literally can't even
  2. You've defined your Item component inside your Teste component which means whenever Teste renders, Item is redefined

I suggest moving Item out of Teste and using a promise-based sleep

const sleep = (ms) => {
  let timer;
  const promise = new Promise(r => {
    timer = setTimeout(r, ms);
  });
  return [ promise, () => { clearTimeout(timer); } ];
};

const Item = ({ nome }) => {
  const [tempo, setTempo] = useState('calculando...');

  useEffect(() => {
    const inicio = new Date();
    const rdm = Math.random();
    const [ delay, cancel ] = sleep(rdm * 1000   2000);
    delay.then(() => {
      setTempo(`${new Date() - inicio} millisegundos`);
    });

    return cancel; // make sure timeout is cleared on unmount
  }, []);

  return (
    <View style={{marginBottom: 20}}>
      <Text>Item {nome}</Text>
      <Text>Tempo - {tempo}</Text>
    </View>
  );
};

const Teste = () => (
  <View style={{padding: 40}}>
    <Item nome="1" />
    <Item nome="2" />
    <Item nome="3" />
  </View>
);

Here sleep() returns both a promise that resolves once the timeout has expired as well as a function to cancel the delay if your component is unmounted.

  • Related