BrowserRouter, але не дозволяє використовувати нові Data APIs (loaders, actions). Використовуйте цей підхід тільки для підтримки старих проектів.До появи Data Router (v6.4+), React Router був суто компонентною бібліотекою. Ми визначали маршрути прямо в JSX, як звичайні компоненти.
Замість createBrowserRouter та RouterProvider, ми використовували компонент-обгортку <BrowserRouter>.
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
{/* Обгортаємо весь додаток */}
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
Маршрути визначаються за допомогою компонентів <Routes> (раніше <Switch> у v5) та <Route>.
import { Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import NotFound from './pages/NotFound';
function App() {
return (
<div className="app">
<header>Моє Меню</header>
<main>
{/* Тут React Router вирішує, що показати */}
<Routes>
{/* path - URL, element - Компонент */}
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
{/* Wildcard маршрут для 404 */}
<Route path="*" element={<NotFound />} />
</Routes>
</main>
</div>
);
}
У старому підході вкладені маршрути можна було робити двома способами.
<Route> (як у v6+)Це схоже на сучасний підхід, але без конфігураційного об'єкта.
<Route path="/dashboard" element={<DashboardLayout />}>
<Route index element={<DashboardHome />} />
<Route path="settings" element={<Settings />} />
</Route>
У цьому випадку DashboardLayout повинен мати <Outlet />.
<Routes> (v5 style)Часто маршрути визначали глибоко всередині компонентів.
<Route path="/dashboard/*" element={<Dashboard />} />
function Dashboard() {
return (
<div>
<h1>Дашборд</h1>
{/* Визначаємо під-маршрути прямо тут */}
<Routes>
<Route path="/" element={<Stats />} />
<Route path="settings" element={<Settings />} />
</Routes>
</div>
);
}
Цей підхід робив код важчим для розуміння, оскільки карта маршрутів була "розмазана" по всьому додатку.
Оскільки у нас немає loader, ми змушені використовувати useEffect для отримання даних. Це призводить до проблеми "водоспадів", описаної в основному курсі.
function ProductPage() {
const { id } = useParams();
const [data, setData] = useState(null);
useEffect(() => {
// Починаємо завантаження тільки після рендеру
fetchProduct(id).then(setData);
}, [id]);
if (!data) return <Spinner />;
return <div>{data.name}</div>;
}
Якщо ви починаєте новий проект, використовуйте тільки createBrowserRouter або routes.ts (v7).
Просунуті Патерни
Ми вже вміємо будувати повноцінні додатки. Але що робити зі складними сценаріями? Авторизація, оптимізація повільних запитів, інтерактивність без переходу на нову сторінку.
Redux: Еволюція управління станом
Повний посібник з Redux: від фундаментальних принципів та "класичного" підходу до сучасного Redux Toolkit та RTK Query.