В библиотеке React Aria функция
mergeProps служит для безопасного объединения нескольких
объектов пропсов в один, обеспечивая корректное слияние обработчиков
событий и атрибутов элементов. Это особенно важно при создании доступных
компонентов, где одни пропсы могут добавляться внутренними хуками
библиотеки, а другие — напрямую разработчиком.
mergeProps(...propsList) принимает любое количество
объектов пропсов и возвращает единый объект, который можно передать
элементу JSX. Основная задача — избежать перезаписи обработчиков
событий и атрибутов, чтобы компоненты корректно реагировали на
пользовательские действия и сохраняли доступность.
Пример базового использования:
import { mergeProps } from '@react-aria/utils';
const buttonPropsFromHook = {
onClick: () => console.log('hook click'),
'aria-label': 'Кнопка'
};
const customButtonProps = {
onClick: () => console.log('custom click'),
className: 'btn-primary'
};
const mergedProps = mergeProps(buttonPropsFromHook, customButtonProps);
/*
mergedProps =
{
onClick: [Function that calls both handlers],
'aria-label': 'Кнопка',
className: 'btn-primary'
}
*/
В этом примере оба обработчика onClick будут вызваны
последовательно при нажатии на кнопку, а атрибут aria-label
сохранится без конфликтов.
Функция mergeProps умеет объединять:
onClick, onMouseEnter,
onMouseLeaveonKeyDown, onKeyUp,
onKeyPressonFocus, onBlurПри объединении нескольких функций обработчика
mergeProps создает цепочку вызовов, где каждый обработчик
вызывается в порядке передачи пропсов, сохраняя контекст
this и аргументы события.
Пример объединения событий клавиатуры:
const props1 = {
onKeyDown: e => console.log('props1 key down')
};
const props2 = {
onKeyDown: e => console.log('props2 key down')
};
const merged = mergeProps(props1, props2);
<button {...merged}>Нажми меня</button>
// Нажатие клавиши вызовет:
// props1 key down
// props2 key down
mergeProps также объединяет атрибуты элементов, такие
как id, aria-* и className.
Поведение при совпадении атрибутов зависит от типа:
Пример объединения классов и стилей:
const propsA = { className: 'btn', style: { color: 'red' } };
const propsB = { className: 'large', style: { backgroundColor: 'blue' } };
const merged = mergeProps(propsA, propsB);
/*
merged =
{
className: 'btn large',
style: { color: 'red', backgroundColor: 'blue' }
}
*/
На практике mergeProps часто используется при интеграции
хуков React Aria, таких как useButton,
useCheckbox или useTextField. Эти хуки
возвращают пропсы, обеспечивающие доступность, а разработчик добавляет
свои кастомные свойства.
Пример с кнопкой:
import { useButton } from '@react-aria/button';
import { mergeProps } from '@react-aria/utils';
function AccessibleButton(props) {
const ref = React.useRef();
const { buttonProps } = useButton(props, ref);
const customProps = {
className: 'btn-primary',
onClick: () => console.log('Кастомное действие')
};
return <button {...mergeProps(buttonProps, customProps)} ref={ref}>
{props.children}
</button>;
}
Здесь:
useButton добавляет обработчики фокуса, клавиатуры и
aria-атрибуты.onClick.mergeProps объединяет всё в единый объект, сохраняя
корректную работу как библиотеки, так и кастомного кода.Порядок аргументов Порядок, в котором передаются
объекты в mergeProps, влияет на приоритет атрибутов и
порядок вызова обработчиков. Первый объект считается базовым,
последующие добавляют новые или объединяют обработчики.
Не изменяет исходные объекты
mergeProps возвращает новый объект, оригинальные пропсы
остаются неизменными, что предотвращает неожиданные побочные
эффекты.
Совместимость с React Объединение функций через
mergeProps полностью безопасно для React — не нарушает
ререндеринг и не создает лишние вызовы.
Рекомендуется для доступных компонентов Любой
компонент, использующий хуки React Aria, должен применять
mergeProps, чтобы не ломать встроенную доступность при
добавлении пользовательских обработчиков или атрибутов.
mergeProps является ключевым инструментом при работе с
React Aria. Он обеспечивает:
Это делает библиотеку гибкой для кастомизации, сохраняя стандарты WAI-ARIA и предотвращая баги, связанные с перезаписью пропсов.