Может быть соблазнительно использовать функциональные обновления , например setArrayIndex((i) => i + 1)
:
Если новое состояние вычисляется с использованием предыдущего состояния, вы можете передать функцию setState.
Однако ваш код должен использовать исходное значение константы arrayIndex
, т. Е. Если оно было 0
к моменту регистрации setTimeout
, вы хотите, чтобы оно было 0
даже через 5 секунд.
Это уже есть в вашем коде - он будет отличаться в разных рендерах (каждый таймер будет иметь разное значение, потому что он был зарегистрирован в другом рендере), но значение никогда не изменитсямежду регистрацией и выполнением таймера (см. Закрытия ).
Что касается улучшений, то можно обнаружить
arrayIndex === 9
даже до регистрации нового setTimeout, например:
useEffect(() => {
if(!startGame || arrayIndex >= 9) return
const timer = setTimeout(() => {
setArrayIndex(arrayIndex + 1)
}, 5000)
return () => clearTimeout(timer)
}, [arrayIndex, startGame])
Более того, если вы хотите, чтобы таймер сбрасывал время рендеринга (т.е. не 5секунд после каждого рендеринга, но с интервалом в 5 секунд) вам понадобится изменяемая ссылка вместо неизменяемого состояния:
const arrayIndexRef = useRef(0)
const arrayIndex = arrayIndexRef.current
useEffect(() => {
if(!startGame) return
const timer = setInterval(() => {
arrayIndexRef.current += 1
if (arrayIndexRef.current >= 9) {
clearInterval(timer)
}
}, 5000)
return () => clearInterval(timer)
}, [startGame])