Содержание
Коротко
Кнопка «Сохранить» ставит статус saved, пока пользователь ещё печатает: замыкание держит старый text. Статья на Dev.to разбирает useLatest из @reactuses/core — стабильный ref, который в layout-эффекте всегда указывает на последнее закоммиченное значение и читается из колбэков после await, таймеров и подписок.
Что произошло
Любой колбэк, переживший свой рендер (await, setTimeout, слушатель, SDK), видит props и state того рендера, где его создали. Это нормальное замыкание; баг — когда нужно «сейчас», а получили «тогда».
useLatest(value) возвращает стабильный ref: .current обновляется в isomorphic layout-эффекте, не во время рендера (concurrent-рендеринг может отбросить рендер). В примере автосохранения замыкание хранит снимок для отправки, ref — текст после ответа API, чтобы выбрать saved или dirty.
Рядом: useEvent / useEffectEvent — для функций; useLatest — для значений. Типовые места: гонка поиска в обработчике, карта или WebSocket с пустым массивом зависимостей, тост с паузой при наведении.
Почему это важно
«Положить state в зависимости эффекта» часто означает рвать дорогую подписку. Ref даёт честный пустой массив зависимостей и свежие данные внутри. Ошибка — читать .current в JSX: для экрана нужен useState.
На практике
- После
awaitсравнивайте отправленный снимок сlatest.current. - Подписки «один раз» читайте через
ref, а не через зависимости, которые пересоздают клиент. - Пишите в
refвlayout-эффекте, не в теле рендера. - Функцию в ребёнка или эффект — через
useEvent; значение в колбэк — черезuseLatest. - Не кладите
refв зависимости «чтобы среагировать» — егоidentityстабилен.
Итог
useLatest — маленький паттерн против устаревших замыканий: всегда актуален из колбэка, не триггерит ререндер и не меняет identity. Для UI по-прежнему state.

