React Aria — это библиотека, предоставляющая высокоуровневые хуки для управления доступностью компонентов в React. Она обеспечивает корректное взаимодействие с пользователем через клавиатуру, экранные считыватели и другие ассистивные технологии. При работе с глобальным состоянием через Redux важно правильно организовать поток данных и обновление состояния, чтобы компоненты React Aria сохраняли свою интерактивность и согласованность состояния.
Начало работы с Redux требует создания хранилища (store)
и подключения его к React-приложению через Provider:
import { configureStore } from '@reduxjs/toolkit';
import { Provider } from 'react-redux';
import rootReducer from './reducers';
const store = configureStore({
reducer: rootReducer,
});
function App() {
return (
<Provider store={store}>
<MainComponent />
</Provider>
);
}
Использование configureStore из
@reduxjs/toolkit позволяет минимизировать шаблонный код и
автоматически подключить Redux DevTools для удобной отладки.
Redux Toolkit предлагает подход слайсов (slice) для
организации состояния:
import { createSlice } from '@reduxjs/toolkit';
const modalSlice = createSlice({
name: 'modal',
initialState: {
isOpen: false,
},
reducers: {
openModal: state => { state.isOpen = true },
closeModal: state => { state.isOpen = false },
},
});
export const { openModal, closeModal } = modalSlice.actions;
export default modalSlice.reducer;
Слайсы упрощают управление состоянием компонентов React Aria, таких как модальные окна или выпадающие списки, где важно синхронизировать визуальное состояние с глобальным состоянием приложения.
React Aria предоставляет хуки для управления элементами интерфейса с
акцентом на доступность. Например, хук useOverlayTrigger
позволяет контролировать открытие и закрытие всплывающих элементов:
import { useOverlayTriggerState } from 'react-stately';
import { useOverlayTrigger, useOverlay } from 'react-aria';
function Modal({ isOpen, onClose }) {
const state = useOverlayTriggerState({ isOpen, onClose });
const ref = React.useRef();
const { overlayProps } = useOverlay({ onClose }, ref);
return (
state.isOpen && (
<div {...overlayProps} ref={ref}>
Содержимое модального окна
</div>
)
);
}
Чтобы синхронизировать состояние с Redux, isOpen и
onClose можно напрямую подключать к глобальному
состоянию:
import { useSelector, useDispatch } from 'react-redux';
import { openModal, closeModal } from './modalSlice';
function ConnectedModal() {
const dispatch = useDispatch();
const isOpen = useSelector(state => state.modal.isOpen);
return (
<Modal
isOpen={isOpen}
onCl ose={() => dispatch(closeModal())}
/>
);
}
React Aria автоматически обрабатывает фокус и навигацию клавиатурой
через свои хуки. Например, при создании выпадающего списка можно
использовать useMenu и useMenuItem:
import { useMenu, useMenuItem } from 'react-aria';
import { useMenuState } from 'react-stately';
function Dropdown({ items }) {
const state = useMenuState({ items });
const ref = React.useRef();
const { menuProps } = useMenu({ items }, state, ref);
return (
<ul {...menuProps} ref={ref}>
{items.map(item => (
<MenuItem key={item.key} item={item} state={state} />
))}
</ul>
);
}
function MenuItem({ item, state }) {
const ref = React.useRef();
const { menuItemProps } = useMenuItem({ key: item.key }, state, ref);
return (
<li {...menuItemProps} ref={ref}>
{item.name}
</li>
);
}
Состояние открытого меню можно хранить в Redux, если требуется глобальная синхронизация:
const isMenuOpen = useSelector(state => state.menu.isOpen);
const dispatch = useDispatch();
Таким образом, React Aria обеспечивает корректное управление фокусом и ARIA-атрибутами, а Redux отвечает за централизованное состояние приложения.
При использовании Redux для управления состоянием, получаемым
асинхронно (например, из API), можно комбинировать React Aria с
createAsyncThunk:
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
export const fetchItems = createAsyncThunk('items/fetch', async () => {
const response = await fetch('/api/items');
return response.json();
});
const itemsSlice = createSlice({
name: 'items',
initialState: { list: [], status: 'idle' },
extraReducers: builder => {
builder
.addCase(fetchItems.pending, state => { state.status = 'loading'; })
.addCase(fetchItems.fulfilled, (state, action) => {
state.status = 'succeeded';
state.list = action.payload;
});
},
});
Комбинация асинхронного состояния Redux и хуков React Aria позволяет строить доступные интерфейсы, которые корректно реагируют на изменения данных без потери доступности.
Для компонентов с несколькими вложенными интерактивными элементами (например, модальные окна с формами и меню) важно:
useOverlay, useMenu,
useDialog для управления доступностью.Эта практика позволяет строить масштабируемые интерфейсы с поддержкой доступности и полной интеграцией с Redux, где глобальное состояние отвечает за бизнес-логику, а React Aria — за корректное взаимодействие пользователя с элементами интерфейса.