Prefetching данных — это процесс предварительной загрузки данных до того момента, когда они реально потребуются компоненту. В React Router эта концепция тесно связана с маршрутизацией, поскольку позволяет уменьшить время ожидания при переходе между страницами, создавая ощущение мгновенной загрузки.
В React Router версии 6 и выше появились встроенные механизмы для управления данными маршрутов через loader-функции. Loader вызывается при переходе на маршрут и может возвращать промис с необходимыми данными. Prefetching заключается в том, чтобы инициировать этот loader заранее.
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import HomePage from "./HomePage";
import AboutPage from "./AboutPage";
const router = createBrowserRouter([
{
path: "/",
element: <HomePage />,
loader: () => fetch("/api/home").then(res => res.json()),
},
{
path: "/about",
element: <AboutPage />,
loader: () => fetch("/api/about").then(res => res.json()),
},
]);
export default function App() {
return <RouterProvider router={router} />;
}
В этом примере loader загружает данные по мере
перехода. Чтобы реализовать prefetching, можно использовать
useFetcher или события наведения мыши.
useFetcheruseFetcher позволяет инициировать запрос данных без
непосредственного перехода на маршрут. Это особенно полезно для
элементов навигации, которые пользователь может кликнуть в ближайшее
время.
import { useFetcher } from "react-router-dom";
function NavLink({ to, children }) {
const fetcher = useFetcher();
return (
<a
href={to}
onMouseEn ter={() => fetcher.load(to)}
>
{children}
</a>
);
}
Здесь при наведении курсора на ссылку запускается загрузка данных, связанных с маршрутом, даже если пользователь ещё не кликнул на неё. Если переход произойдет, данные уже будут готовы.
onFocus и onHoverReact Router поддерживает стратегию prefetching, основанную на пользовательских действиях, таких как наведение мыши или фокус на элементе. Использование этих стратегий снижает нагрузку на сеть и ускоряет восприятие интерфейса.
<a
href="/about"
onMouseEn ter={() => fetcher.load("/about")}
onFo cus={() => fetcher.load("/about")}
>
О нас
</a>
В этом подходе комбинируются два события: onMouseEnter
для пользователей мыши и onFocus для пользователей
клавиатуры, обеспечивая доступность.
<Link>Компонент <Link> из React Router 6.4+ поддерживает
встроенный prefetch через свойство prefetch. Это позволяет
указать стратегию, которая будет автоматически применяться при рендере
ссылки.
import { Link } from "react-router-dom";
<Link to="/about" prefetch="intent">
О нас
</Link>
Параметр prefetch="intent" означает, что данные маршрута
будут загружены при намерении пользователя перейти (например, при
наведении курсора). Альтернативно можно использовать
prefetch="render", чтобы загружать данные сразу при рендере
компонента.
Когда маршруты имеют вложенную структуру, prefetching должен учитывать загрузку данных всех уровней. React Router позволяет комбинировать loader-функции для вложенных маршрутов:
const router = createBrowserRouter([
{
path: "/dashboard",
element: <Dashboard />,
loader: () => fetch("/api/dashboard").then(res => res.json()),
children: [
{
path: "stats",
element: <Stats />,
loader: () => fetch("/api/stats").then(res => res.json()),
},
{
path: "reports",
element: <Reports />,
loader: () => fetch("/api/reports").then(res => res.json()),
},
],
},
]);
Для prefetching можно вызывать loader конкретного дочернего маршрута, когда пользователь взаимодействует с элементами меню, не загружая сразу всю страницу.
intent):
загружать данные при первом сигнале пользователя о намерении перейти
(hover, focus).render):
загружать данные сразу при монтировании ссылки или навигационного
элемента. Подходит для часто посещаемых маршрутов.Loader-функции возвращают промисы, поэтому при prefetching необходимо
обрабатывать ошибки. Можно использовать try/catch или
встроенные возможности React Router:
loader: async () => {
try {
const res = await fetch("/api/data");
if (!res.ok) throw new Error("Ошибка загрузки");
return res.json();
} catch (error) {
return { error: error.message };
}
}
Для кеширования prefetching-запросов можно использовать
react-query или встроенный кеш fetcher, чтобы данные не
загружались повторно при повторном наведении.
React Router совместим с React Suspense, что позволяет показывать placeholder-контент, пока данные загружаются:
import { Suspense } from "react";
import { Await } from "react-router-dom";
<Suspense fallback={<div>Загрузка...</div>}>
<Await resolve={loaderData}>
{(data) => <Component data={data} />}
</Await>
</Suspense>
Suspense удобно сочетать с prefetching: при переходе пользователь видит индикатор загрузки только в случае, если данные не успели подгрузиться заранее.
Prefetching данных в React Router повышает отзывчивость приложений, сокращает задержки при навигации и позволяет реализовать стратегически продуманные подходы к загрузке ресурсов, от простого hover-prefetch до интеграции с Suspense и кешированием данных.