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

const IntroPage = () => {
  const [progressBarValue, setProgressBarValue] = useState(0)
  useEffect(() => {
    setInterval(function() {
      let val = progressBarValue;
      val += Math.floor(Math.random() * 10) + 5;

      if (val >= 100) {
        val = 100;
      }

      setProgressBarValue(val)
    }, 1000);
  }, [])

  return (
    <div className='main-container'>
      <div></div>
      <div className='progress-bar-container'>
        <ProgressBar className='progress-bar' value={progressBarValue}></ProgressBar>
      </div>
      <div></div>
    </div>
    )
}

По какой-то причине, когда я загружаю страницу, индикатор выполнения не всегда достигает 100, он перемещается туда и обратно, и я не совсем уверен, почему это происходит. Таким образом, он будет увеличиваться до 8 или 10%, затем опустится до 6 и т. Д. Я думаю, проблема в том, что каждый раз, когда устанавливается новое состояние, оно не добавляется к предыдущему установленному состоянию. Любая помощь будет оценена по достоинству.

Обновление: я также попытался поместить setInterval в отдельную функцию и вызвать ее, но это также делает то же самое -

 useEffect(() => {
             loadProgressBar() 
        }  
    }, [])

 function loadProgressBar() {
        setInterval(function(){ 
            let val = progressBarValue;
            val += Math.floor(Math.random() * 10) + 5;

            if (val >= 100) {
                val = 100;
                clearInterval();
            }

            setProgressBarValue(val)
        }, 1000);
    }

1
monkeys73 13 Окт 2020 в 16:55

1 ответ

Лучший ответ

Это неправильный способ использования функции интервала внутри useEffect вы можете узнать больше здесь

Правильный путь таков:

useEffect(() => {
    const intervalId = setInterval(() => {
      setProgressBarValue((prev) => {
        if (prev >= 100) {
          clearInterval(intervalId);
          return 100;
        } else {
          return prev + 5;
        }
      });
    }, 1000);
    return () => clearInterval(intervalId);
  }, []);

LIVE DEMO

Проблема с вашей реализацией заключается в том, что progressBarValue не обновляется внутри useEffect.
Обратный вызов setInterval компилируется один раз, а затем запускается (то же значение / ссылка функции и ее аргументов) каждые 1000 мс, поскольку массив зависимостей пуст.
Это означает, что он считывает начальное значение progressBarValue и не считывает следующие значения просто, потому что это не зависимость для useEffect.

В моей реализации setProgressBarValue() использует обратный вызов для чтения предыдущего значения состояния и его увеличения.

1
Tasos Bu 13 Окт 2020 в 18:26