useFocusWithin — это хук из библиотеки React
Aria, предназначенный для отслеживания фокуса внутри контейнера
и управления соответствующими состояниями. Он полезен в интерфейсах, где
требуется визуально или логически реагировать на фокус дочерних
элементов, например, при создании кастомных форм, списков или
интерактивных панелей.
Фокус внутри контейнера определяется как состояние,
когда хотя бы один элемент внутри контейнера получил фокус. В отличие от
стандартного события onFocus, которое срабатывает на
отдельном элементе, useFocusWithin отслеживает весь
контейнер и его потомков, предоставляя удобный способ централизованной
обработки фокуса.
Ключевые возможности хука:
isFocusWithin).onFocusWithinChange.import { useFocusWithin } from '@react-aria/interactions';
import { useRef } from 'react';
function FocusContainer() {
const ref = useRef();
const { focusWithinProps, isFocusWithin } = useFocusWithin({
onFocusWithinChange: (isFocused) => console.log('Фокус внутри:', isFocused)
});
return (
<div {...focusWithinProps} ref={ref} style={{
border: isFocusWithin ? '2px solid blue' : '2px solid gray',
padding: '16px',
borderRadius: '8px'
}}>
<input type="text" placeholder="Имя" />
<input type="text" placeholder="Фамилия" />
</div>
);
}
Разбор кода:
ref привязывает контейнер к DOM-элементу.focusWithinProps включает все необходимые обработчики
событий (onFocus, onBlur) для отслеживания
фокуса.isFocusWithin — булевое значение, которое становится
true, если любой дочерний элемент контейнера получил
фокус.Хук позволяет задать функции обратного вызова:
onFocusWithinChange – вызывается при
каждом изменении состояния фокуса внутри контейнера. Аргумент
isFocused указывает, находится ли фокус внутри
контейнера.onFocusWithin и
onBlurWithin – отдельные события для начала и
окончания фокуса внутри контейнера.const { focusWithinProps } = useFocusWithin({
onFocusWithin: () => console.log('Фокус появился внутри контейнера'),
onBlurWithin: () => console.log('Фокус покинул контейнер')
});
Эти обработчики позволяют выполнять анимации, переключать классы или управлять видимостью элементов, реагируя на активность пользователя внутри группы элементов.
Использование isFocusWithin удобно для динамической
стилизации контейнера:
<div {...focusWithinProps} ref={ref} className={isFocusWithin ? 'focused' : ''}>
...
</div>
В CSS:
.focused {
border: 2px solid #3b82f6;
box-shadow: 0 0 4px rgba(59,130,246,0.5);
}
Это позволяет визуально показывать, что контейнер активен, без необходимости навешивать обработчики на каждый дочерний элемент вручную.
useFocusWithin отлично сочетается с:
usePress — для отслеживания нажатий
внутри контейнера.useHover — для комбинирования фокуса и
наведения.useOverlay — для управления фокусом в
модальных окнах и всплывающих панелях.import { useFocusWithin, useHover } from '@react-aria/interactions';
const { focusWithinProps, isFocusWithin } = useFocusWithin();
const { hoverProps, isHovered } = useHover();
<div {...focusWithinProps} {...hoverProps}>
{isFocusWithin && <span>Фокус внутри</span>}
{isHovered && <span>Наведение</span>}
</div>
Такой подход упрощает создание сложных интерактивных компонентов с несколькими состояниями.
ref на контейнере, а не
на отдельных элементах. Хук работает на всей группе дочерних
элементов.onFocus и
onBlur на потомках, чтобы не нарушать логику
хука.:focus-within, если необходима только визуальная
подсветка, но useFocusWithin позволяет также управлять
логикой компонента.function ProfileForm() {
const nameRef = useRef();
const emailRef = useRef();
const nameFocus = useFocusWithin({ ref: nameRef });
const emailFocus = useFocusWithin({ ref: emailRef });
return (
<form>
<div {...nameFocus.focusWithinProps} ref={nameRef} className={nameFocus.isFocusWithin ? 'active' : ''}>
<input type="text" placeholder="Имя" />
</div>
<div {...emailFocus.focusWithinProps} ref={emailRef} className={emailFocus.isFocusWithin ? 'active' : ''}>
<input type="email" placeholder="Email" />
</div>
</form>
);
}
Этот пример демонстрирует, как можно отслеживать фокус внутри отдельных блоков формы и динамически изменять их стиль.
useFocusWithin позволяет создать единый источник правды
о состоянии фокуса внутри контейнера, упрощает управление интерактивными
компонентами и снижает количество ручного кода для отслеживания
активности пользователя. Такой подход особенно ценен при создании
доступных интерфейсов и кастомных UI-компонентов, где важно корректное
управление фокусом.