Невозможно получить доступ к состоянию внутри интервала - PullRequest
3 голосов
/ 23 октября 2019

Я не могу получить доступ к состоянию в течение определенного интервала. Здесь я хочу получить доступ к счетчику внутри интервала, когда счетчик становится равным 10, я хочу остановить его.

Примечание: Здесь я не хочу помещать интервал внутри useEffect, потому что мне нужно запустить интервал в определенное время, обрабатывая событие.

export default props => {

  const [counter, setCounter] = useState(0);

  const startInterval = () => {
    const timeout = setInterval(() => {
      setCounter(counter + 1);
      console.log("counter: ", counter); // alway return 0
      if(counter === 10) clearInterval(timeout);

    }, 1000);
  };

} 

Ответы [ 2 ]

2 голосов
/ 23 октября 2019

Как я вижу здесь, даже ваш setCounter(counter+1) не будет обновляться из-за лексической области видимости. Таким образом, вы должны изменить его следующим образом:

setCounter(counter => counter + 1);

Также из-за лексической области действия вы не получите доступ к счетчику для проверки условия, поэтому вам нужно создать переменную и обновить ее внутри функционального компонента, назначив ему счетчик,затем проверьте его, если условие.

Полный код:

let myCounter = 0;
let timeout = null;
export default CounterApp = props => {

  const [counter, setCounter] = useState(0);

  // Also don't forget this
  useEffect(()=> {
    return ()=> clearInterval(timeout);
  }, []);      

  myCounter = counter;
  const startInterval = () => {
    timeout = setInterval(() => {
      setCounter(counter => counter + 1);
      console.log("counter: ", myCounter); // counter always return 0 but myCounter the updated value
      if(myCounter === 10) clearInterval(timeout);

    }, 1000);
  };

}
1 голос
/ 23 октября 2019

Я столкнулся с этой проблемой не так давно. Хуки не работают точно так, как вы ожидаете от setInterval. Я нашел решение в блоге Дана Абрамова : Вы можете useRef объединить несколько useEffect с. Благодаря его реализации useInterval вы также можете запускать и останавливать интервал, установив таймер на null

import React, { useState, useEffect, useRef } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  const [time, setTime] = useState(null); // timer doesn't run initially

  useInterval(() => {
    // Your custom logic here
    setCount(count + 1);
  }, time);

  return <>
     <h1>{count}</h1>
     <div onClick={() => setTime(1000)}>Start</div>
     <div onClick={() => setTime(null)}>Stop</div>
  </>;
}
import React, { useState, useEffect, useRef } from 'react';

function useInterval(callback, delay) {
  const savedCallback = useRef();

  // Remember the latest callback.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null) {
      let id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...