React Router предоставляет мощные инструменты для маршрутизации в приложениях на React, а Context API позволяет организовывать глобальное состояние. Совмещение этих двух технологий обеспечивает гибкую и централизованную маршрутизацию с доступом к состоянию приложения на любом уровне дерева компонентов.
Контекст может использоваться для хранения информации о текущем
состоянии маршрутов, параметрах URL или дополнительных данных,
необходимых для навигации. Например, можно создать контекст
NavigationContext, который будет хранить текущий путь и
методы для его изменения:
import { createContext, useContext, useState } from 'react';
const NavigationContext = createContext();
export const NavigationProvider = ({ children }) => {
const [currentPath, setCurrentPath] = useState('/');
const navigate = (path) => {
setCurrentPath(path);
};
return (
<NavigationContext.Provider value={{ currentPath, navigate }}>
{children}
</NavigationContext.Provider>
);
};
export const useNavigation = () => useContext(NavigationContext);
В этом примере создается провайдер, который предоставляет объект с текущим путем и функцией навигации. Такой подход позволяет компонентам получать доступ к маршрутизации без прямого использования React Router.
React Router предоставляет компонент BrowserRouter и
хуки useNavigate, useLocation,
useParams, которые можно совместить с контекстом для
централизованного управления навигацией.
Пример интеграции:
import { BrowserRouter, Routes, Route, useNavigate, useLocation } from 'react-router-dom';
import { NavigationProvider, useNavigation } from './NavigationContext';
const RouterIntegration = () => {
const navigate = useNavigate();
const location = useLocation();
const { setCurrentPath } = useNavigation();
// Обновление контекста при смене маршрута
useEffect(() => {
setCurrentPath(location.pathname);
}, [location.pathname, setCurrentPath]);
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
);
};
const App = () => (
<BrowserRouter>
<NavigationProvider>
<RouterIntegration />
</NavigationProvider>
</BrowserRouter>
);
В этом подходе Context API и React Router работают вместе: контекст
хранит актуальный путь, а RouterIntegration синхронизирует
состояние контекста с useLocation. Это упрощает управление
навигацией в крупных приложениях.
Контекст можно использовать для хранения параметров маршрутов, чтобы передавать их глубоко вложенным компонентам без необходимости пропс-дриллинга.
const ParamsContext = createContext();
export const ParamsProvider = ({ children }) => {
const location = useLocation();
const [params, setParams] = useState({});
useEffect(() => {
const searchParams = new URLSearchParams(location.search);
const newParams = {};
for (const [key, value] of searchParams.entries()) {
newParams[key] = value;
}
setParams(newParams);
}, [location.search]);
return <ParamsContext.Provider value={params}>{children}</ParamsContext.Provider>;
};
export const useParamsContext = () => useContext(ParamsContext);
Теперь любой компонент внутри ParamsProvider может
получить доступ к параметрам URL:
const SearchResults = () => {
const params = useParamsContext();
return <div>Результаты поиска: {params.query}</div>;
};
С помощью контекста можно реализовать глобальные методы навигации, которые доступны в любом компоненте, даже вне компонентов React Router. Например, для открытия модального окна по маршруту:
const GlobalNavigation = () => {
const { navigate } = useNavigation();
const openModal = () => {
navigate('/modal');
};
return <button onCl ick={openModal}>Открыть модальное окно</button>;
};
Такой метод позволяет отделить логику навигации от конкретного компонента маршрутов, что повышает модульность приложения.
Контекст удобно использовать для реализации защиты маршрутов. Например, для проверки авторизации пользователя перед переходом на определённый маршрут:
const AuthContext = createContext();
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
const login = (userData) => setUser(userData);
const logout = () => setUser(null);
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
};
const PrivateRoute = ({ children }) => {
const { user } = useContext(AuthContext);
return user ? children : <Navigate to="/login" />;
};
Теперь маршруты можно защищать через компонент
PrivateRoute:
<Routes>
<Route path="/dashboard" element={<PrivateRoute><Dashboard /></PrivateRoute>} />
</Routes>
Контекст API позволяет хранить глобальное состояние авторизации и использовать его для принятия решений о доступе к маршрутам.
Комбинирование React Router и Context API упрощает синхронизацию состояния приложения с URL. Например, можно сохранять состояние фильтров, пагинации или выбранных элементов в URL, а через контекст предоставлять его всем компонентам.
const FilterContext = createContext();
export const FilterProvider = ({ children }) => {
const location = useLocation();
const [filters, setFilters] = useState({});
useEffect(() => {
const searchParams = new URLSearchParams(location.search);
setFilters(Object.fromEntries(searchParams.entries()));
}, [location.search]);
return <FilterContext.Provider value={{ filters, setFilters }}>{children}</FilterContext.Provider>;
};
Такое решение обеспечивает прямую связь состояния приложения с URL, облегчая работу с закладками, историей и внешними ссылками.
Контекст API и React Router совместно позволяют создавать масштабируемые, управляемые и централизованные приложения, где маршрутизация и состояние тесно интегрированы, а доступ к ним возможен на любом уровне дерева компонентов.