React Router – это незаменимый инструмент для создания навигации в приложениях React, и его最新版本ы продолжают улучшать опыт разработчиков с новыми функциями и улучшениями производительности. Начиная с версии 7 (или других грядущих версий), React Router добавляет продвинутые функции, такие как вложенные маршруты и маршруты-макеты, которые помогают создавать robust и эффективные веб-приложения.
Основные Новые Функции в React Router 7 (или Последней Версии)
Вот некоторые из значительных улучшений и функций, представленных в最新ой версии:
1. Упрощенное Определение Маршрутов С Использованием API Данных
Новые API данных, такие как loader
и action
, позволяют fetch и изменять данные более декларативным способом внутри маршрутов.
В более старых версиях, fetch данных обычно обрабатывался внутри компонентов React с использованием useEffect
или методов жизненного цикла классовых компонентов. Это часто приводило к тому, что логика fetch данных смешивалась с рендерингом интерфейса, что могло become неудобным.
Пример React Router v5
import { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
function UserPage() {
const { id } = useParams();
const [userData, setUserData] = useState(null);
useEffect(() => {
fetch(`/api/users/${id}`)
.then((response) => response.json())
.then((data) => setUserData(data));
}, [id]);
return (
<div>
<h1>User: {userData?.name}</h1>
</div>
);
}
Последние версии introduce Loader
API, позволяющие fetch данных происходить напрямую на уровне маршрута. Это separates проблемы, упрощает компоненты и enables лучшее одновременное рендеринг.
Пример React Router v7
import { useLoaderData } from 'react-router-dom';
export async function userLoader({ params }) {
const response = await fetch(`/api/users/${params.id}`);
return response.json();
}
function UserPage() {
const userData = useLoaderData();
return (
<div>
<h1>User: {userData.name}</h1>
</div>
);
}
// Route Configuration
<Route path="/users/:id" element={<UserPage />} loader={userLoader} />
Разница
В React Router 7 логика получения данных (userLoader
) разведена с компонентом, что делает компоненты纯粹 ориентированными на отрисовку. Этот подход также позволяетprefetch данные перед отрисовкой компонента, что способствует лучшему опыту пользователя и более плавным переходам.
2. Error Boundaries Per Route
Одной из полезных функций, introducedException в React Router 7 (или более новых версиях), является возможность определения Error Boundaries для каждого маршрута. Это позволяет разработчикам обрабатывать ошибки на болееfine-grained уровне. Вместо того чтобы иметь единую глобальную границу ошибок для всего приложения, вы можете определить границы ошибок, специфичные для отдельных маршрутов, делая обработку ошибок более гибкой и локализованной. Granular error handling на уровне маршрута теперь возможен.
В более старых версиях обработка ошибок была глобальной или управляемой на уровне компонента. Это требовало от разработчиков обрабатывать все возможные ошибки в одном месте или внедрять сложную логику в различных компонентах. Как указано в следующем примере, ErrorBoundary
глобален, так как он обертывает весь Router
, что означает, что он будет перехватывать ошибки со всех маршрутов в приложении.
Пример React Router v5
function App() {
return (
<ErrorBoundary>
<Router>
<Route path="/" exact component={HomePage} />
<Route path="/about" component={AboutPage} />
</Router>
</ErrorBoundary>
);
}
React Router 7 introduces границы ошибок на уровне маршрута, что делает возможным обработку ошибок для конкретных маршрутов. Это позволяет более точно управлять тем, как ошибки обрабатываются и отображаются.
Пример React Router v7
import { useRouteError } from 'react-router-dom';
function ErrorBoundary() {
const error = useRouteError();
return <div>Error: {error.message}</div>;
}
<Route path="/users/:id" element={<UserPage />} errorElement={<ErrorBoundary />} />
Разница
Обработка ошибок в React Router 7 стала более модульной и локализованной. Each route может определить свою логику обработки ошибок, что улучшает пользовательский опыт при сбоях в различных частях приложения.
3. Лучшая обработка маршрутов layouts
Маршруты layouts introduцируются, что позволяет для последовательного управления layouts в различных частях приложения, уменьшая дублирование кода.
В React Router v5, layouts, такие как заголовки, футеры или панели, должны были быть ручно дублированы в каждом маршруте или компоненте. Это означало, что разработчики часто помешали компоненты layouts (например, Header
, Footer
) напрямую внутри компонента App
или дублировали их через различные обработчики маршрутов, как показано в вашем примере.
Пример React Router v5
import { BrowserRouter as Router, Route } from 'react-router-dom';
import Header from './Header';
import Footer from './Footer';
import HomePage from './HomePage';
import AboutPage from './AboutPage';
function App() {
return (
<Router>
<Header />
<Route path="/" exact component={HomePage} />
<Route path="/about" component={AboutPage} />
<Footer />
</Router>
);
}
React Router 7 introduces маршруты layouts, где вы можете определить общие layouts, которые обертывают вложенные маршруты, устраняя дублирование кода и обеспечивая лучшую структуру.
Пример React Router v7
import { Outlet } from 'react-router-dom';
function SharedLayout() {
return (
<div>
<header>Header Content</header>
<main>
<Outlet /> {/* Nested routes will render here */}
</main>
<footer>Footer Content</footer>
</div>
);
}
// Route Configuration with Layout
<Route path="/" element={<SharedLayout />}>
<Route index element={<HomePage />} />
<Route path="about" element={<AboutPage />} />
</Route>
Разница
Маршруты layouts позволяют применить чистый, повторно используемый способ применения общих layouts через несколько маршрутов, без повторения кода. Outlet
acts as a placeholder for child routes, что значительно упрощает управление layouts.
4. Улучшенные возможности вложенных маршрутов
Существуют более эффективные ways для обработки вложенных маршрутов, включая наследование элементов layouts и лучшие стратегии получения данных.
В более старых версияхnested маршруты были возможны, но настройка была более сложной. Приходилось явно обрабатывать nesting маршрутов внутри родительского компонента, используя useRouteMatch()
для получения текущего пути, а затем вручную определять nested маршруты внутри родительского компонента. Этот подход может быстро стать сложным, особенно для сложных приложений с несколькими уровнями nested маршрутов.
Пример React Router v5
import { Route, useRouteMatch } from 'react-router-dom';
function Dashboard() {
const { path } = useRouteMatch();
return (
<div>
<h1>Dashboard</h1>
<Route path={`${path}/overview`} component={Overview} />
<Route path={`${path}/settings`} component={Settings} />
</div>
);
}
<Route path="/dashboard" component={Dashboard} />
В React Router 7, nested маршруты теперь настраиваются декларативно, напрямую внутри конфигурации маршрутов, что упрощает структуру маршрутизации и делает код более читаемым.
Пример React Router v7
import { Outlet } from 'react-router-dom';
function DashboardLayout() {
return (
<div>
<h1>Dashboard</h1>
<Outlet /> {/* Nested routes will render here */}
</div>
);
}
// Route Configuration
<Route path="/dashboard" element={<DashboardLayout />}>
<Route path="overview" element={<Overview />} />
<Route path="settings" element={<Settings />} />
</Route>
Разница
В React Router 7,nested маршруты проще управлять,因为他们 определяются на уровне конфигурации маршрутов с использованием компонента Outlet
. Эта структура promotes четкое разделение между макетом и содержимым.
5. Улучшенная интеграция Suspense
Теперь есть лучшая поддержка React 18’ого Suspense
и concurrent рендеринга для более плавного опыта загрузки.
В более старых версиях, suspense поддерживался только для lazy-loaded компонентов, что ограничивало его полезность для сложных сценариев загрузки данных.
Пример React Router v5
import React, { Suspense, lazy } from 'react';
const HomePage = lazy(() => import('./HomePage'));
<Suspense fallback={<div>Loading</div>}>
<Route path="/" component={HomePage} />
</Suspense>
React Router 7 интегрирует Suspense
с его Loader и Action API, что позволяетfetching данных параллельно и с минимальными усилиями.
Пример React Router v7
import { Suspense } from 'react';
import { Route, Routes } from 'react-router-dom';
function App() {
return (
<Suspense fallback={<div>Loading</div>}>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
</Routes>
</Suspense>
);
}
Разница
React Router 7 использует Suspense
как для отложенного загрузки компонентов, так и для fetching данных, что позволяет achieve более плавные переходы и болееresponsive интерфейс.
Заключение
React Router 7 (или самая последняя версия) значительно улучшает маршрутизацию в приложениях React, introducing несколько мощных функций. Новые Loader и Action API enable декларативный fetching данных, что позволяет отделить логику данных от компонентов для cleaner кода. Layout Routes упрощают управление общими макетами, уменьшая избыточность. Nested routes стали более эффективными и интуитивными, позволяя clearer структуру. Дополнительно, границы ошибок на маршруте предоставляют granular обработку ошибок, улучшая надежность. Полная интеграция с React Suspense
поддерживает более smooth загрузку данных и пользовательские впечатления. Вместе, эти усовершенствования упрощают разработку сложных, масштабируемых и производительных приложений React, делая React Router 7 значительным улучшением по сравнению с предыдущими версиями.
Source:
https://dzone.com/articles/why-react-router-7-is-a-game-changer-for-react-devs