Таймеры и очистка
Эффекты — место и для таймеров. В курсе JavaScript вы запускали их с помощью setInterval() и останавливали с помощью clearInterval(). В React их запускает эффект. Вот обратный отсчёт до открытия ворот фестиваля:
import { useEffect, useState } from "react";
export default function GatesCountdown() {
const [secondsLeft, setSecondsLeft] = useState(60);
useEffect(() => {
const id = setInterval(() => {
setSecondsLeft((secondsLeft) => secondsLeft - 1);
}, 1000);
return () => clearInterval(id);
}, []);
return <p>Ворота откроются через {secondsLeft} с</p>;
}Здесь важны три вещи:
- Зависимости
[]. Интервал запускается один раз, когда компонент появляется, и дальше работает сам. Без массива эффект запускался бы снова после каждой отрисовки, то есть каждую секунду, и каждый раз останавливал бы и запускал интервал заново. - Функция-обновитель. Функция интервала была создана при первой отрисовке, когда
secondsLeftбыло равно 60, и это значение у неё остаётся.setSecondsLeft(secondsLeft - 1)снова и снова задавало бы 59. Функция-обновитель каждый раз получает текущее значение. - Очистка. Функция, которую возвращает эффект, — это его очистка. React вызывает её, когда компонент исчезает со страницы, а также перед тем, как снова запустить эффект из-за изменившейся зависимости. Здесь она останавливает интервал.
Зачем интервалу очистка? Компонент может исчезнуть, пока его интервал ещё работает. В этом упражнении таймер исчезает, когда выступление заканчивается. Без очистки интервал об этом не знает: он продолжает менять состояние компонента, которого уже нет на странице, пока открыта страница, а каждый раз, когда таймер показывают снова, к нему добавляется ещё один интервал.
Задание
- 1
В
StageTimer.jsxдобавьте эффект с зависимостями[], который запускает интервал: каждые 1000 миллисекунд он увеличиваетsecondsна 1 с помощью функции-обновителя(seconds) => seconds + 1. Сохраните идентификатор интервала в константеid: он понадобится на следующем шаге. - 2
Остановите интервал с помощью очистки: эффект возвращает
() => clearInterval(id). Прежде чем её добавить, посмотрите, что она меняет: поместитеconsole.log("тик");в функцию интервала, закончите выступление и посмотрите в консоль. Тики продолжаются. С очисткой они прекращаются, когда выступление заканчивается.