Как ранняя установка рефов влияет на доступ к ним
Что проверяют
Понимаете ли вы, в какой момент React записывает DOM-узел в ref.current и почему до этого там null. Следом обычно просят объяснить, как измерить элемент до отрисовки и чем колбэк-реф отличается от useRef.
Как отвечать
Главная мысль: реф заполняется не во время рендера, а на фазе коммита. Порядок такой:
- рендер: функция компонента выполняется, JSX с
ref={inputRef}только описывает будущий узел. На первом рендереinputRef.currentравенnull, на следующих в нём прежний узел; - коммит: React обновляет DOM, у удаляемых и изменённых элементов сбрасывает рефы в
null, затем записывает новые узлы; useLayoutEffect: реф уже заполнен, а браузер ещё не отрисовал кадр. Здесь меряют размеры черезgetBoundingClientRectи ставят тултип на место без мигания;useEffect: реф тоже доступен, подходит для фокуса, подписок и сторонних библиотек.
Рефы дочерних элементов заполняются раньше, чем выполняются эффекты родителя, поэтому родитель может в своём эффекте работать с DOM ребёнка.
Если нужен сам момент подключения узла, берут колбэк-реф: функция в ref вызывается с узлом при монтировании. В React 19 она может вернуть функцию очистки, и тогда при размонтировании React вызовет её вместо вызова с null. Там же ref стал обычным пропом у функциональных компонентов, и forwardRef для новых компонентов не нужен.
Реф не заполнится вовсе, если элемента нет в DOM: условный рендер, Suspense в ожидании, ещё не загруженный ленивый компонент.
Где спотыкаются
Читают ref.current прямо в теле компонента и передают ребёнку пропсом. На первом рендере там null, а дальше значение устаревает, потому что смена рефа не вызывает ререндер.
Кладут ref.current в массив зависимостей useEffect и ждут перезапуска эффекта при смене узла. React не следит за рефами, для этого нужен колбэк-реф или состояние.
Измеряют элемент в useEffect, когда от размеров зависит позиция. Пользователь успевает увидеть кадр со старой позицией, здесь нужен useLayoutEffect.