Какой React хук используется для хранения предыдущего значения
Что проверяют
Различаете ли вы значение, которое переживает рендер, и значение, которое рендер вызывает. Готового хука для предыдущего значения в React нет, поэтому вопрос быстро превращается в проверку понимания useRef и момента выполнения эффектов. Следом обычно просят написать usePrevious.
Как отвечать
Скажите прямо: отдельного хука для этого нет, предыдущее значение держат в useRef. Ref это изменяемая ячейка, которая переживает рендеры, и запись в неё не вызывает повторный рендер.
Стандартный usePrevious устроен так: заводите ref, в useEffect записываете в него текущее значение, а из хука возвращаете ref.current. Работает за счёт порядка: эффект выполняется после коммита, поэтому во время рендера в ref.current ещё лежит значение прошлого рендера.
- почему не
useState: запись в состояние вызовет ещё один рендер, а тот новую запись, и получится цикл; - типы: в типах React 19
useRefобязан получить аргумент, пишитеuseRef(undefined), иначе TypeScript ругается; useLayoutEffectвместоuseEffect, если предыдущее значение нужно, чтобы что-то измерить или подправить в DOM до отрисовки кадра;- первый рендер: вернётся
undefined, этот случай обрабатывайте явно.
Сильный ответ добавляет альтернативу из документации React: если предыдущее значение нужно только для того, чтобы по смене пропса поправить состояние, эффект не нужен. Храните копию пропса в useState и сравнивайте прямо в теле компонента, вызывая сеттеры до возврата разметки. React перезапустит рендер компонента до отрисовки, и промежуточный кадр пользователь не увидит.
Назовите применения: направление анимации, событие аналитики «было и стало», запуск запроса только когда идентификатор действительно поменялся.
Где спотыкаются
Пишут ref.current = value прямо в теле компонента и там же читают. Тогда «предыдущее» совпадает с текущим, а под конкурентным рендером такая запись во время рендера ещё и небезопасна.
Тянут usePrevious туда, где нужно обычное состояние. Если прошлое значение видно пользователю, это данные, им место в useState.
Забывают про первый рендер и рисуют «было undefined» на экране или ломают на этом сравнение.