Перехват useEffect с использованием устаревших переменных в дочерних функциях

#reactjs #use-effect

#reactjs #использование-эффект

Вопрос:

Я пытаюсь использовать перехват useEffect как способ создания асинхронного таймера в react. Логика находится внутри timeFunc(), и useEffect работает так, что вызывает функцию каждые 1000 мс. Странная часть заключается в том, что по какой-то причине, когда timeFunc() вызывается (каждую секунду), он обращается только к старым значениям переменных (в частности, «приостановлено»). Например, если интервал начинается со значения «приостановлено», равного false, даже если я изменю значение «приостановлено» на true (приостановлено — это переменная состояния, переданная родительским компонентом), timeFunc() все равно будет считать, что приостановлено равно false . Не могу понять. Любая помощь приветствуется!

Код:

   //TIMER MANAGER
  let timeFunc = () => {
    if(paused == false){
      let delta = Math.trunc((new Date() - resumedTime)/1000);
      setProgress(delta);
      console.log('test   '   paused);
    } else {
      clearInterval(interval);
    }
  }
  useEffect(() => {
      let interval = null;
        interval = setInterval(() => {
          timeFunc();
        }, 1000);
      return () => clearInterval(interval);
    }, [initialized]);
 

Ответ №1:

timeFunc Зависит от наличия актуального значения paused , но оно не существует в useEffect массиве зависимостей.

Либо добавьте его в массив зависимостей, а также сохраните время до следующего интервала в состоянии, либо используйте ссылку paused вместо (со стабильной ссылкой) (или в дополнение к состоянию), например:

 const pausedRef = useRef(false);
// ...
const timeFunc = () => {
  if (!pausedRef.current) {
    // ...
 
 // to change it:
pausedRef.current = !pausedRef.current;
 

Также обратите внимание, что

 let interval = null;
  interval = setInterval(() => {
    timeFunc();
  }, 1000);
 

упрощает

 const interval = setInterval(timeFunc, 1000);