Устаревшее замыкание
Вопрос
Что такое stale closure в React и как это чинить?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
колбэк запомнил значения того рендера, в котором был создан
типично: setInterval из useEffect с пустыми зависимостями
внутри навсегда остаётся начальное значение состояния
лечение: функциональная форма setState
лечение: честные зависимости и пересоздание эффекта
лечение: ref для значения, которое нужно читать всегда свежим
Что могут спросить следом
- Почему функциональная форма setState решает проблему
- Когда ref - правильное решение, а когда костыль
- Как это выглядит в обработчике, привязанном к window
Разбор
Каждый рендер создаёт новые функции, замкнутые на значения этого рендера.
Если колбэк пережил рендер - например, попал в setInterval из эффекта с [] - он
навсегда видит старое состояние.
useEffect(() => {
const id = setInterval(() => setCount(count + 1), 1000); // count всегда 0
return () => clearInterval(id);
}, []);
Три лечения: функциональная форма setCount(c => c + 1) - не нужно читать текущее
значение; честные зависимости - эффект пересоздастся; useRef, который обновляют в эффекте,
если нужно читать всегда актуальное без пересоздания подписки.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Предыдущий вопрос
useEffect: зависимости и очистка
Следующий вопрос
Отмена запроса через AbortController