Почему не появляется фокус на инпуте после рендера
Что проверяют
Понимаете ли вы, в какой момент узел реально появляется в документе, и знаете ли условия, при которых focus() вообще срабатывает. Заодно смотрят, где в React место императивному обращению к DOM.
Как отвечать
Разбирать по порядку проверки.
Узла ещё нет. ref.current равен null, если фокус ставят в теле компонента или в эффекте родителя выше по дереву. Ставить фокус надо в эффекте того компонента, где само поле, либо через колбэк-ref.
const focusRef = useCallback((node) => { node?.focus(); }, []);
return <input ref={focusRef} />;Элемент не может принять фокус. disabled, display: none, visibility: hidden, атрибут hidden, поле внутри свёрнутого родителя: вызов проходит молча, и ничего не происходит. Неинтерактивному элементу нужен tabindex.
Фокус перехватили позже. Ловушка фокуса в модалке, автофокус чужого компонента, повторное монтирование из-за смены key. Проверяется просто: посмотреть document.activeElement через небольшую задержку, не трогая мышь.
Элемент появляется с анимацией или через портал. Тогда ждать не таймером наугад, а через requestAnimationFrame или событие окончания перехода.
Мобильный Safari открывает клавиатуру только в ответ на жест: программный фокус вне обработчика пользовательского события там игнорируется.
Где спотыкаются
Лечат нулевым setTimeout вслепую. Иногда помогает, потому что колбэк выполняется после коммита, но причина остаётся, и на медленном устройстве баг возвращается. Сначала выяснить, есть ли узел.
Путают useEffect и useLayoutEffect. Оба идут после вставки в DOM, разница в том, что первый выполняется уже после отрисовки кадра. Для фокуса это редко заметно, а вот порядок «сначала дети, потом родитель» ломает наивный код в родителе.
Ставят автофокус там, где он мешает. На телефоне он выдвигает клавиатуру и сдвигает вёрстку, скринридеру перебивает чтение заголовка. Фокус уместен там, где его ждут: поле поиска, первое поле только что открытой модалки.