Каждый раз, когда я открываю официальную документацию React Router, я поражаюсь: API снова изменилось! Давайте посмотрим, какие обновления доступны на этот раз.
хороший парень!Да Я понимаюсерединаиз React Router ?
Когда я разрабатывал «Коллекцию онлайн-настольных игр» в марте 2022 года, я использовал 6.2 версия того времени v6 и v5 v4 По сравнению с API Произошло относительно большое событиеизизменять,但я认可этот些изменять。
Посмотрите это сейчас 6.4 документация по версии, Я хочу пожаловаться. Моя основная точка зрения: Реагировать Router 6.4 Это больше не просто маршрут, он объединяет логику данных.
Ниже этой статьи объективное введение: React Router 6.4 Представляем новые функции Data API и дать в конце Субъективный заключение。
createXXXXRouter
APIсуществовать React Router 6.4 середина,Новый Понятно 3 индивидуальный createXXXXRouter
API для поддержки data API:
То есть, да,Если вам не нужен этот 3индивидуальный API,идакартинаv6.0
-v6.3
Такой же,прямойиспользовать<BrowserRouter>
ждать Следующие несколькоиндивидуальныйAPI,Тогда вы не сможете пользоваться API данных.
createXXXXRouter
использованиенеобходимо объединить<RouterProvider>
Вместеиспользовать。можно увидеть,этоиспользоватьодининдивидуальный Конфигурация,Определить маршруты.
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
createBrowserRouter,
RouterProvider,
} from "react-router-dom";
const router = createBrowserRouter([
{
path: "/",
element: <Root />,
children: [
{
path: "team",
element: <Team />,
},
],
},
]);
ReactDOM.createRoot(document.getElementById("root")).render(
<RouterProvider router={router} />
);
когда Ран,Если вы предпочитаете определять маршруты с использованием синтаксиса JSX,картина<BrowserRouter>
Такой же:
<BrowserRouter>
<Routes>
<Route index element={<div />} />
</Routes>
</BrowserRouter>
React Router 6.4 также добавил конфигурацию JSX,ссылкаcreateRoutesFromElements,это有另外одининдивидуальный ИмяcreateRoutesFromChildren。
const router = createBrowserRouter(
createRoutesFromElements(
<Route path="/" element={<Root />}>
<Route path="dashboard" element={<Dashboard />} />
<Route path="about" element={<About />} />
</Route>
)
);
<Route>
изизменятькогдатыиспользоватьcreateXXXXRouter
и<RouterProvider>
час,Вы можете использовать API данных.
Сказав все это, что такое Data API?
Фактически, да позволяет вам записать «логику получения данных» в определение маршрутизации середина. Каждый раз, когда маршрут там переключается, данные автоматически поступают.
мы начинаем с<Route>
изизменять Сразу Может看出,это Новый Понятно3индивидуальный Связанныйизсвойство:
<Route>
loader свойствоloaderсвойство传入одининдивидуальныйфункция(позволятьда async функция), выполняйте функцию каждый раз перед рендерингом «этот маршрут соответствует элементу». существования「Этот маршрут соответствует изelement」, вы можете использовать hook useLoaderData
(будет обсуждаться нижепредставлять)Приходитьполучатьэтотиндивидуальныйфункцияизвозвращаемое значение (обычно это ответ на HTTP-запрос).
<Route
loader={async ({ request }) => {
// loaders can be async functions
const res = await fetch("/api/user.json", {
signal: request.signal,
});
const user = await res.json();
return user;
}}
element={<Xxxxxx />}
/>
загрузчиксвойство входящей функции, позволяющей использовать 2индивидуальных параметра:
/user/:userId
,параметр Сразуда:userId
,Вы можете передать params.userId для получения значения параметра маршрута).request
Удобно получать, когда изпараметр предыдущей страницы:<Route
loader={async ({ request }) => {
const url = new URL(request.url);
const searchTerm = url.searchParams.get("q");
return searchProducts(searchTerm);
}}
/>
Мне не нужен этот индивидуальный параметр запроса, хорошо? Нет?,因为еслитыиспользоватьwindow.location
получатьизинформациядакогдапредыдущий последнийизценить,Если пользователь быстро нажимает кнопку,Пусть страница направляется на A,и сразу направиться к B,этотчас候路由AПерепискаRouteизloaderполучатьwindow.location
час,Можно получить неправильное значение.
Обратите внимание, проходите request,Также есть индивидуальные льготы,это有индивидуальный request.signal, когда пользователь быстро нажимает кнопку, чтобы направить страницу к A и сразу к B. Запрос страницы Aизloader должен быть отменен. Вы можете пройти. signal Реализация следующая:
<Route
loader={async ({ request }) => {
return fetch("/api/teams.json", {
signal: request.signal,
});
}}
/>
функцияизвозвращаемое значение,Сможет существоватьэлементсередина через крючок useLoaderData
(См. ниже) Приходите получать. Что вы возвращаете, то и получаете.
но React Router Официальная консультация, возврат к индивидуальному Веб-спецификации серединаиз Fetch API из Response。
Вы можете напрямую return fetch(url, config);
,Вы также можете составить индивидуальный ответ самостоятельно:
function loader({ request, params }) {
const data = { some: "thing" };
return new Response(JSON.stringify(data), {
status: 200,
headers: {
"Content-Type": "application/json; utf-8",
},
});
}
//...
<Route loader={loader} />
Вы также можете пройти React Router Предоставить из json построить:
import { json } from "react-router-dom";
function loader({ request, params }) {
const data = { some: "thing" };
return json(data, { status: 200 });
}
//...
<Route loader={loader} />
redirect
существовать loader , вам может потребоваться перенаправление после проверки, React Router Не рекомендуется вам использовать useNavigation Завершено, рекомендуется существовать непосредственно loader средний прямой return перенаправление, переход на новый URL-адрес.
import { redirect } from "react-router-dom";
const loader = async () => {
const user = await getUser();
if (!user) {
return redirect("/login");
}
};
Если получить данные не удалось,или другая любая причина,ты认为Нет能让 Route Переписка element После нормального рендеринга вы можете существовать loader середина throw аномальный. В это время будет отображен «errorElement».
function loader({ request, params }) {
const res = await fetch(`/api/properties/${params.id}`);
if (res.status === 404) {
throw new Response("Not Found", { status: 404 });
}
return res.json();
}
//...
<Route loader={loader} />
Уведомление:ты можешьбросить любойаномальный,все будет в порядкесуществовать errorElement пройти внутри hook useRouteError
Приходитьполучатьприезжатьаномальный。
но,React Router Официальный совет вам throw Response:
<Route
path="/properties/:id"
element={<PropertyForSale />}
errorElement={<PropertyError />}
loader={async ({ params }) => {
const res = await fetch(`/api/properties/${params.id}`);
if (res.status === 404) {
throw new Response("Not Found", { status: 404 });
}
const home = res.json();
return { home };
}}
/>
ты все еще можешь использовать его React Router Предоставить из json Метод, удобная конструкция индивидуальная Response:
throw json(
{ message: "email is required" },
{ status: 400 },
);
<Route>
element свойствоэтотиндивидуальный Нетдановыйсвойство,Прямо сейчас<Route
После сопоставления,Рендеринг контента. Я хочу, чтобы это было из изменений:
useLoaderData
получать loader возвращаемое значениеОбратите внимание, что если loader возвращаемое значениеда Ответ и Response из Content Type да application/json,React Router Он будет автоматически вызван внутри .json() метод, разработчику не нужно писать .json() .
function Albums() {
const albums = useLoaderData();
return <div>{albums}</div>;
}
const router = createBrowserRouter([
{
path: "/",
loader: fetch("/api"),
element: <Albums />,
},
]);
ReactDOM.createRoot(el).render(
<RouterProvider router={router} />
);
useRouteLoaderData
получать другой Route из loader возвращаемое значениеКомпоненты React могут быть вложенными,<Route>
Также может быть вложенным,этотчас Можетпроходить该 hook получатьдругой <Route>
из loader извозвращаемое значение. когда Однако вам необходимо предоставить id。
При определении маршрута:
createBrowserRouter([
{
path: "/",
loader: () => fetchUser(),
element: <Root />,
id: "root",
children: [
{
path: "jobs/:jobId",
loader: loadJob,
element: <JobListing />,
},
],
},
]);
<JobListing />
Внутри部调использоватьэтотиндивидуальныйhookчас:
const user = useRouteLoaderData("root");
<Route>
errorElement свойствокогда loader брошенный внутрьаномальный,<Route>
Сразу Нет渲染этоиз element , в то время как да отображает его из errorElement。
<Route>
да может быть вложенным, и каждый уровень может быть определен errorElement, возникает аномальный элемент, будет найден ближайший из errorElement и отобразите его, а затем перестаньте всплывать.
useRouteError
получатьаномальныйсуществовать errorElement внутри, доступен useRouteError
получатьаномальный。
const error = useRouteError();
isRouteErrorResponse
Определить тип исключенияReact Router 给Понятноодининдивидуальныйфункция isRouteErrorResponse
,帮тысуществоватьразвивать errorElement Когда когда раньше аномальныйда ли да Response аномальный. потому что Response аномальный в целомдаразвивать者自己抛出из,да может отображать причину (включая код ошибки, возвращаемый внутренним интерфейсом, и копию подсказки об ошибке),Также возможносуществоватьэтотвнутри处理)。другойаномальный,Обычно неизвестно из,Просто отобразите копию отчета об ошибках напрямую.
function RootBoundary() {
const error = useRouteError();
if (isRouteErrorResponse(error)) {
if (error.status === 404) {
return <div>This page doesn't exist!</div>;
}
if (error.status === 503) {
return <div>Looks like our API is down</div>;
}
}
return <div>Something went wrong</div>;
}
<Route>
action свойствоВидите ли, это очень похоже на лаодер:
useActionData
получать action возвращаемое значение. (похожий useLoaderData
)Разница в том, что они выполняются в разное время:
Написал раньше<form>
из Все знают,Имеет параметр действия и метода.,существоватьдо,Отправка формы также меняет URL-адрес в браузере. использовать сообщение React,почти никто этого не делает,Все отправляют формы через AJAX или Fetch.
сейчассуществовать,React Router предоставил <Form>
компоненты,и дать <Route>
добавлены компоненты action
свойство, позволяющее отправке формы стать одноразовым маршрутом.
Действительно, я больше не могу с этим поделать и хочу опубликовать его. мнение:Это кажется бесполезным, это бесполезно。
если хочешь знать Route из action свойство, надо посмотреть React Router Form,Уведомление Form внутри也有индивидуальный action собственность, не путайтесь.
когда Ран,React Router 6.4 Не только Data API У этого человека есть еще одно крупное обновление: Отложено. Data: Deferred Data Guide。
Не могу не написать еще раз лично мнение: Зачем добавлять эту индивидуальную функцию? да Чтобы дать Data API «Вытри задницу».
Из-за введения загрузчика возникают внутренние запросы API, что неизбежно приводит к тому, что страница загружается долго при переключении маршрутизации. Что делать, если загрузка длится долго? Необходимо показать состояние загрузки.
React Router Доступны оба варианта. Первый вариант — да. useFetcher。为Понятно实сейчас方案二,это引入Понятноdefer
функцияи<Await>
компоненты。
существовать loader Внутрииспользовать,表明этотиндивидуальный loader Нужно показать Loading состояние. если loader вернулся отложить, тогда он будет отображен напрямую <Route>
из element。
<Route
loader={async () => {
let book = await getBook(); // Этот человек не будет отображаться Loading государство, потому что это await Да, оно будет выполнено и данные будут получены.
let reviews = getReviews(); // этотиндивидуальныйвстречавыставка Loading состояние
return defer({
book, // Эти данные
reviews, // Да promise
});
}}
element={<Book />}
/>;
<Await>
компонентысуществовать <Route>
из element серединаиспользовать,использовать于выставка Loading состояние.нужно объединить<Suspense>
использовать,Loading состояниевыставкасуществовать<Suspense>
из fallback середина。
function Book() {
const {
book,
reviews, // this is the same promise
} = useLoaderData();
return (
<div>
<h1>{book.title}</h1>
<p>{book.description}</p>
<React.Suspense fallback={<ReviewsSkeleton />}>
<Await
// and is the promise we pass to Await
resolve={reviews}
>
<Reviews />
</Await>
/>
</React.Suspense>
</div>
);
}
ждать loader После загрузки он будет отображаться Await из children внутрииз Внутри容.
<Await>
компонентыиз children свойствоЭто может быть дафункция, а может быть да React-компоненты.
Если дафункция, результатом Promise будет дапараметр:
<Await resolve={reviewsPromise}>
{(resolvedReviews) => <Reviews items={resolvedReviews} />}
</Await>
Если дакомпоненты,Внутри部проходитьuseAsyncValue
получать Promise из результатов.
<Await resolve={reviewsPromise}>
<Reviews />
</Await>;
function Reviews() {
const resolvedReviews = useAsyncValue();
return <div>{/* ... */}</div>;
}
Повторю свою основную мысль: React Router 6.4 Это больше не просто маршрут, он объединяет логику данных.
Публичные зависимости:
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
После упаковки следующего кода 141199 B.
import React from 'react';
import ReactDOM from 'react-dom/client';
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
<React.StrictMode>
<div />
</React.StrictMode>,
);
После упаковки следующего кода 150266 B.
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
<React.StrictMode>
<BrowserRouter>
<Routes>
<Route index element={<div />} />
</Routes>
</BrowserRouter>
</React.StrictMode>,
);
Код тот же, что и выше, 159758 B.
После упаковки следующего кода 196040 B.
import React from 'react';
import ReactDOM from 'react-dom/client';
import {
createBrowserRouter,
RouterProvider,
} from 'react-router-dom';
import './index.css';
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
const router = createBrowserRouter([
{
index: true,
element: <div />,
},
]);
root.render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>,
);
упаковочный материал | Объем (Б) | Рост из Объема (Б) | Относительный темп роста 6,3 | Доля React Router в общем коде |
---|---|---|---|---|
Нет React-маршрутизатора | 141199 | 0 | - | - |
React Router 6.3 | 150266 | 9067 | 1x | 6% |
React Router 6.4 не использует API данных | 159758 | 18559 | 2,05 раза | 12% |
React Router 6.4 с использованием API данных | 196040 | 54841 | 6,05 раз | 28% |
В конечном итоге я хотел бы использовать react-router-dom=~6.3.0
,Прямо сейчас Нет更новыйприезжать 6.4, всегда используйте 6.3.x。
после всего,яиз«Коллекция настольных онлайн-игр»внутри,HTTP-запросов нет. Я просто хочу использовать чистые компоненты индивидуального маршрута. А 6.4 нацелен на 6.3 издругой мелких фич,Я вообще не могу его использовать.
Я да Халл Цинь,Официальный аккаунтОфлайн-игры для вечеринокизавтор(добро пожаловатьсосредоточиться меня, заведи индивидуальных друзей). Перед пересылкой этой статьи необходимо разрешение автора HullQin. Я самостоятельно разработал «Коллекцию настольных онлайн-игр»,индивидуальная веб-страница,Друзьям очень удобно играть в ООН, Помещики, нарды, Летающие шахматы, Один Ночной Волк, шахматы, Немецкая Болезнь Сердца, Код Да Винчи ждать онлайн.,Нет收费никторекламировать。还развивать Понятно《Dice Crush》УчастиеGame Jam 2022。喜欢Можетсосредоточиться ная噢~я有空Понятновстреча分享做游戏из Связанный技术,встречасуществоватьэтотиндивидуальный专栏внутри分享:《Научите вас играть в маленькие игры》。