React Router 7 به تازگی منتشر شده است و بهروزرسانیهای بسیار مفیدی را شامل میشود. در این مقاله قصد داریم تا درمورد تغییرات نسخه React Router 7 بیشتر صحبت کنیم و یاد بگیریم که چگونه باید از این ویژگیهای جدید در پروژههای خود استفاده کنیم.
تغییرات React Router 7 شامل چه مواردی میباشد؟
۱- Type Safety پیشرفته
یکی از مهمترین تغییرات در نسخه ۷، سیستم Type Safety پیشرفته است. اکنون میتوانیم از بررسی قویتر تایپ و پشتیبانی از تکمیل خودکاری که بهبود پیدا کرده است در IDE خود بهرهمند شویم.
// Before (React Router 6)
const loader = async ({ params }) => {
const user = await getUser(params.id);
// After (React Router 7)
const loader = async ({ params }: LoaderFunctionArgs) => {
const user = await getUser(params.id);
return json(user); // Type-safe response
// Before (React Router 6)
const loader = async ({ params }) => {
const user = await getUser(params.id);
return user;
};
// After (React Router 7)
const loader = async ({ params }: LoaderFunctionArgs) => {
const user = await getUser(params.id);
return json(user); // Type-safe response
};
// Before (React Router 6)
const loader = async ({ params }) => {
const user = await getUser(params.id);
return user;
};
// After (React Router 7)
const loader = async ({ params }: LoaderFunctionArgs) => {
const user = await getUser(params.id);
return json(user); // Type-safe response
};
۲- دریافت سادهتر دادهها
React Router 7 یک رویکرد شهودیتر برای دریافت داده با استفاده از loader و action APIهای بهبود یافته معرفی میکند. این پیادهسازی جدید، مدیریت dependencyهای داده و مدیریت stateهای loading را آسانتر مینماید.
// New data fetching pattern in v7
loader: async ({ params }) => {
const response = await fetch(`/api/users/${params.id}`);
return json(await response.json());
// New data fetching pattern in v7
export const route = {
loader: async ({ params }) => {
const response = await fetch(`/api/users/${params.id}`);
return json(await response.json());
},
element: <UserProfile />
};
// New data fetching pattern in v7
export const route = {
loader: async ({ params }) => {
const response = await fetch(`/api/users/${params.id}`);
return json(await response.json());
},
element: <UserProfile />
};
۳- بهبود مدیریت خطا
مدیریت خطا در نسخه ۷ با کنترل دقیقتر بر روی error boundaryها، ارتقاء اساسی پیدا میکند. اکنون میتوانیم مدیریت خطا را در سطح route تعریف کنیم که این کار، مدیریت و دیباگ کردن خطاها را آسانتر میکند.
const router = createBrowserRouter([
errorElement: <DashboardError />,
errorElement: <AnalyticsError />, // Specific error handling
const router = createBrowserRouter([
{
path: "/dashboard",
element: <Dashboard />,
errorElement: <DashboardError />,
children: [
{
path: "analytics",
element: <Analytics />,
errorElement: <AnalyticsError />, // Specific error handling
loader: analyticsLoader
}
]
}
]);
const router = createBrowserRouter([
{
path: "/dashboard",
element: <Dashboard />,
errorElement: <DashboardError />,
children: [
{
path: "analytics",
element: <Analytics />,
errorElement: <AnalyticsError />, // Specific error handling
loader: analyticsLoader
}
]
}
]);
۴- بهبود Suspense Integration
React Router 7 یکپارچگی بهتری را با ویژگی React 18 Suspense ارائه مینماید که کمک میکند تا stateهای loading ظریفتر و تجربه کاربری بهتری را داشته باشیم:
import { Suspense } from 'react';
import { Await, useLoaderData } from 'react-router-dom';
const { product } = useLoaderData();
<Suspense fallback={<ProductSkeleton />}>
<Await resolve={product}>
{(resolvedProduct) => <ProductDetails product={resolvedProduct} />}
import { Suspense } from 'react';
import { Await, useLoaderData } from 'react-router-dom';
function ProductPage() {
const { product } = useLoaderData();
return (
<Suspense fallback={<ProductSkeleton />}>
<Await resolve={product}>
{(resolvedProduct) => <ProductDetails product={resolvedProduct} />}
</Await>
</Suspense>
);
}
import { Suspense } from 'react';
import { Await, useLoaderData } from 'react-router-dom';
function ProductPage() {
const { product } = useLoaderData();
return (
<Suspense fallback={<ProductSkeleton />}>
<Await resolve={product}>
{(resolvedProduct) => <ProductDetails product={resolvedProduct} />}
</Await>
</Suspense>
);
}
بررسی تغییراتی که قبل از ارتقا پروژه باید توجه بیشتری به آنها داشته باشیم
قبل از این که React Router پروژه خود را به نسخه ۷ ارتقا دهیم، باید از این تغییرات مهم اطلاع داشته باشیم زیرا، ممکن است برنامه ما را تحت تأثیر قرار دهند:
۱- Required بودن آبجکتهای Response
export async function loader() {
return { message: "Hello" };
// This is the correct way in v7
export async function loader() {
return json({ message: "Hello" });
// This won't work in v7
export async function loader() {
return { message: "Hello" };
}
// This is the correct way in v7
export async function loader() {
return json({ message: "Hello" });
}
// This won't work in v7
export async function loader() {
return { message: "Hello" };
}
// This is the correct way in v7
export async function loader() {
return json({ message: "Hello" });
}
۲- تغییر در پیکربندی Route
در نسخه جدید، سینتکس پیکربندی route بهروزرسانی شده است تا صریحتر و ایمنتر باشد:
<Route path="/dashboard" element={<Dashboard />}>
<Route path="profile" element={<Profile />} />
const router = createBrowserRouter([
// Old way (v6)
<Routes>
<Route path="/dashboard" element={<Dashboard />}>
<Route path="profile" element={<Profile />} />
</Route>
</Routes>
// New way (v7)
const router = createBrowserRouter([
{
path: "/dashboard",
element: <Dashboard />,
children: [
{
path: "profile",
element: <Profile />,
loader: profileLoader
}
]
}
]);
// Old way (v6)
<Routes>
<Route path="/dashboard" element={<Dashboard />}>
<Route path="profile" element={<Profile />} />
</Route>
</Routes>
// New way (v7)
const router = createBrowserRouter([
{
path: "/dashboard",
element: <Dashboard />,
children: [
{
path: "profile",
element: <Profile />,
loader: profileLoader
}
]
}
]);
۳- بهروزرسانی Navigation API
برای این که navigation API شهودیتر بوده و سازگاری بیشتری داشته باشد، در نسخه ۷ اصلاحاتی داشته است:
preventScrollReset: true,
// Old way (v6)
navigate('/dashboard');
// New way (v7)
navigation.navigate({
to: '/dashboard',
// New options available
preventScrollReset: true,
relative: 'path'
});
// Old way (v6)
navigate('/dashboard');
// New way (v7)
navigation.navigate({
to: '/dashboard',
// New options available
preventScrollReset: true,
relative: 'path'
});
بررسی روش ارتقا به نسخه ۷ React Router
در ادامه یک راهنمای گامبهگام برای ارتقا به نسخه ۷ را باهم بررسی میکنیم:
آمادهسازی محیط توسعه
ابتدا باید مطمئن شویم که پروژه ما حداقل شرایط لازم برای انجام این کار را برآورده میکند:
# Update to React 18 if you haven't already
npm install react@18 react-dom@18
npm install react-router-dom@7
# Update to React 18 if you haven't already
npm install react@18 react-dom@18
# Install React Router 7
npm install react-router-dom@7
# Update to React 18 if you haven't already
npm install react@18 react-dom@18
# Install React Router 7
npm install react-router-dom@7
بهروزرسانی تعاریف route
مسیرهای موجود خود را به فرمت جدید تبدیل میکنیم:
import { createBrowserRouter } from 'react-router-dom';
export const router = createBrowserRouter([
errorElement: <DashboardError />
// src/router.tsx
import { createBrowserRouter } from 'react-router-dom';
export const router = createBrowserRouter([
{
path: '/',
element: <RootLayout />,
children: [
{
path: 'dashboard',
element: <Dashboard />,
loader: dashboardLoader,
errorElement: <DashboardError />
}
]
}
]);
// src/router.tsx
import { createBrowserRouter } from 'react-router-dom';
export const router = createBrowserRouter([
{
path: '/',
element: <RootLayout />,
children: [
{
path: 'dashboard',
element: <Dashboard />,
loader: dashboardLoader,
errorElement: <DashboardError />
}
]
}
]);
بهروزرسانی منطق دریافت داده
برای این که بتوانیم از loader و الگوهای action جدید استفاده کنیم، باید data fetching خود را مجدداً تنظیم نماییم:
const [data, setData] = useState(null);
fetchDashboardData().then(setData);
return <div>{/* render data */}</div>;
export async function loader() {
const data = await fetchDashboardData();
const data = useLoaderData();
return <div>{/* render data */}</div>;
// Before (v6)
function Dashboard() {
const [data, setData] = useState(null);
useEffect(() => {
fetchDashboardData().then(setData);
}, []);
return <div>{/* render data */}</div>;
}
// After (v7)
export async function loader() {
const data = await fetchDashboardData();
return json(data);
}
function Dashboard() {
const data = useLoaderData();
return <div>{/* render data */}</div>;
}
// Before (v6)
function Dashboard() {
const [data, setData] = useState(null);
useEffect(() => {
fetchDashboardData().then(setData);
}, []);
return <div>{/* render data */}</div>;
}
// After (v7)
export async function loader() {
const data = await fetchDashboardData();
return json(data);
}
function Dashboard() {
const data = useLoaderData();
return <div>{/* render data */}</div>;
}
آیا لازم است که React Router را به نسخه ۷ ارتقا دهیم؟
تصمیم برای ارتقا باید بر اساس نیازها و شرایط خاص ما باشد. در ادامه نکاتی وجود دارد که حتما باید به آنها توجه کنیم:
اگر
- به پشتیبانی بهتر تایپ اسکریپت نیاز داریم
- الگوهای بهبود یافته برای data fetching را میخواهیم
- در حال شروع یک پروژه جدید هستیم
- و یا این که در حال حاضر در نسخه ۶ هستیم و جدیدترین ویژگیها را میخواهیم، در این صورت بهتر است که React Router را به نسخه ۷ ارتقا دهیم
اما اگر
- تنظیمات فعلی پروژه پایدار است و به خوبی کار میکند
- در مراحل میانی یک پروژه قرار داریم
- React Router خود را هنوز به نسخه ۶ ارتقا ندادهایم
- و یا برای تست کامل پروژه پس از ارتقا به زمان نیاز داریم، در این صورت بهتر است از انجام این کار صرف نظر کنیم.
جمعبندی
React Router 7 یک گام مهم رو به جلو از نظر type safety، data fetching و تجربه توسعهدهنده میباشد. در حالی که برخی از توسعهدهندگان نگرانیهای مربوط به performance را گزارش کردهاند، اما پیشرفتهای کلی در API و فانکشنالیتی، آن را به یک ارتقای قانع کننده برای بسیاری از پروژهها تبدیل کرده است.
باید به این نکته توجه داشته باشیم که پس از ارتقاء برنامه خود به نسخه ۷، پروژه خود را به شکل کامل تست کنیم، زیرا اعمال یکسری از تغییرات ممکن است به روشهای غیرمنتظرهای بر روی منطق routing پروژه ما تأثیر بگذارد.
دیدگاهها: