Как правильно настроить таймер setInterval в функциональном компоненте React?

Я только начал изучать реакцию и смотрел 9X_react учебник, посвященный состоянию и хукам. Он 9X_react-component просто занимается обновлением времени каждые 9X_react-jsx 1000 миллисекунд (по крайней мере, я так 9X_javascript-library думал).

import React from "react"; let count = 0; function App() { const now = new Date().toLocaleTimeString(); let [time, setTime] = React.useState(now); function updateTime(){ const newTime = new Date().toLocaleTimeString(); setTime(newTime); count++; console.log(count); console.log(new Date().getMilliseconds()); } setInterval(updateTime, 1000); return ( 

{time}

 ); } export default App; 

Целью учебника был простой пример 9X_react того, как обновлять время, но я заметил, что 9X_react-dom оно обновляется несколько раз (пакетами) каждые 9X_reactjs 1000 миллисекунд. Я подозреваю, что каждый 9X_ecmascript раз, когда происходит изменение ловушки, отображается 9X_react-jsx новый компонент, но старый компонент все 9X_react.js еще обновляется и порождает больше компонентов, что 9X_vanillajs приводит к тому, что кажется экспоненциальным 9X_.js ростом вызовов каждые 1000 миллисекунд.

Мне 9X_react-component очень любопытно, что здесь происходит? Как 9X_javascript я могу, скажем, иметь простой счетчик, который 9X_vanillajs обновляется каждые 1000 миллисекунд? setTime(count) явно 9X_vanilla-javascript не работает

9
1

  • В этой статье конкретно рассматривается setInterval в компонентах функционального реагирования https://overrected.io/making-setinterva ...
3
Общее количество ответов: 3

Ответ #1

Ответ на вопрос: Как правильно настроить таймер setInterval в функциональном компоненте React?

Проблема: в вашей текущей реализации setInterval будет 9X_react-dom вызываться каждый раз при рендеринге компонента 9X_reactjs (т. е. также будет вызываться после установки 9X_vanillajs временного состояния) и будет создавать новый интервал - что привело 9X_react-dom к такому «экспоненциальному росту», как 9X_javascript видно на вашей консоли.

Как объясняется в 9X_react.js разделе комментариев: useEffect - лучший способ справиться 9X_react с этим сценарием при работе с функциональными 9X_react-component компонентами в React. Взгляните на мой пример 9X_react-component ниже. useEffect здесь будет запускаться только после 9X_vanilla-javascript первоначального рендеринга компонента (когда 9X_ecmascript компонент монтируется).

React.useEffect(() => { console.log(`initializing interval`); const interval = setInterval(() => { updateTime(); }, 1000); return () => { console.log(`clearing interval`); clearInterval(interval); }; }, []); // has no dependency - this will be called on-component-mount 

Если вы хотите запустить 9X_javascript-library эффект и очистить его только один раз (при 9X_react-component монтировании и unmount), вы можете передать 9X_javascript пустой массив ([]) в качестве второго аргумента. Этот сообщает 9X_javascript-library React, что ваш эффект не зависит от каких-либо 9X_react-component значений из props или состояние, поэтому 9X_vanillajs его не нужно запускать повторно.

В вашем 9X_vanilla-javascript сценарии это идеальное использование «пустого 9X_react-jsx массива в качестве второго аргумента», поскольку 9X_react-component вам нужно будет только установить интервал, когда 9X_react компонент монтируется, и очистить интервал, когда 9X_ecmascript он размонтируется. Взгляните на функцию, которую 9X_react-component возвращает useEffect. Это наша функция очистки, которая 9X_.js запускается при отключении компонента. Это 9X_vanillajs «очистит» или, в данном случае, очистит 9X_js интервал, когда компонент больше не используется.

Я 9X_react-jsx написал небольшое приложение, демонстрирующее 9X_react все, что я рассмотрел в этом ответе: https://codesandbox.io/s/so-react-useeffect-component-clean-up-rgxm0?file=/src/App.js

Я добавил 9X_vanilla-javascript небольшую функцию маршрутизации, чтобы можно 9X_vanillajs было наблюдать "размонтирование" компонента.


Мой 9X_reactjs старый ответ (не рекомендуется):

Новый интервал 9X_react.js создается каждый раз при повторном рендеринге 9X_react компонента, что и происходит, когда вы устанавливаете 9X_react-dom новое состояние для времени. Я бы очистил 9X_js предыдущий интервал (clearInterval) перед установкой 9X_vanillajs нового

try { clearInterval(window.interval) } catch (e) { console.log(`interval not initialized yet`); } window.interval = setInterval(updateTime, 1000); 

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval

15
0

Ответ #2

Ответ на вопрос: Как правильно настроить таймер setInterval в функциональном компоненте React?

Как ответил Макро Аморим, лучший способ 9X_react-component сделать это - useEffect. Вот код:

useEffect(() => { const interval = setInterval(() => { const newTime = new Date().toLocaleTimeString(); setTime(newTime); }, 1000) return () => { clearInterval(interval); } }, [time]) 

4
0

Ответ #3

Ответ на вопрос: Как правильно настроить таймер setInterval в функциональном компоненте React?

Вы также можете попробовать это -

import React, { useEffect, useState } from 'react'; export default function App() { const [timer, setTimer] = useState(0); const [toggle, setToggle] = useState(false); useEffect(() => { let counter; if (toggle) { counter = setInterval(() => setTimer(timer => timer + 1), 1000); } return () => { clearInterval(counter); }; }, [toggle]); const handleStart = () => { setToggle(true); }; const handleStop = () => { setToggle(false); }; const handleReset = () => { setTimer(0); setToggle(false); }; return ( 

Hello StackBlitz!

Current timer - {timer}


 ); } 

9X_react.js

2
0