從 v6 升級
在本頁面中

從 v6 升級

React Router v7 需要以下最低版本

  • node@20
  • react@18
  • react-dom@18

如果您已啟用所有未來標誌,則 v7 升級沒有重大變更。這些標誌讓您可以一次更新應用程式一個變更。我們強烈建議您在每個步驟後進行提交並發布,而不是一次完成所有操作。

更新到最新的 v6.x 版本

首先更新到最新的 v6.x 次要版本,以擁有最新的未來標誌和控制台警告。

👉 更新到最新的 v6 版本

npm install react-router-dom@6

v7_relativeSplatPath

背景

變更多段 splat 路徑(例如 dashboard/*,相對於僅 *)的相對路徑匹配和連結。查看更新日誌以取得更多資訊。

👉 啟用標誌

啟用標誌取決於路由器的類型

<BrowserRouter
  future={{
    v7_relativeSplatPath: true,
  }}
/>
createBrowserRouter(routes, {
  future: {
    v7_relativeSplatPath: true,
  },
});

更新您的程式碼

如果您有任何路徑加上 splat 的路由,例如 <Route path="dashboard/*">,且在其下方有相對連結,例如 <Link to="relative"><Link to="../relative">,則您需要更新程式碼。

👉 <Route> 分割成兩個

將任何多段 splat <Route> 分割成具有路徑的父路由和具有 splat 的子路由

<Routes>
  <Route path="/" element={<Home />} />
-  <Route path="dashboard/*" element={<Dashboard />} />
+  <Route path="dashboard">
+    <Route path="*" element={<Dashboard />} />
+  </Route>
</Routes>

// or
createBrowserRouter([
  { path: "/", element: <Home /> },
  {
-    path: "dashboard/*",
-    element: <Dashboard />,
+    path: "dashboard",
+    children: [{ path: "*", element: <Dashboard /> }],
  },
]);

👉 更新相對連結

更新該路由樹中的任何 <Link> 元素,以包含額外的 .. 相對段,以繼續連結到相同的位置

function Dashboard() {
  return (
    <div>
      <h2>Dashboard</h2>
      <nav>
-        <Link to="/">Dashboard Home</Link>
-        <Link to="team">Team</Link>
-        <Link to="projects">Projects</Link>
+        <Link to="../">Dashboard Home</Link>
+        <Link to="../team">Team</Link>
+        <Link to="../projects">Projects</Link>
      </nav>

      <Routes>
        <Route path="/" element={<DashboardHome />} />
        <Route path="team" element={<DashboardTeam />} />
        <Route
          path="projects"
          element={<DashboardProjects />}
        />
      </Routes>
    </div>
  );
}

v7_startTransition

背景

這使用 React.useTransition 而不是 React.useState 來更新 Router 狀態。查看更新日誌以取得更多資訊。

👉 啟用標誌

<BrowserRouter
  future={{
    v7_startTransition: true,
  }}
/>

// or
<RouterProvider
  future={{
    v7_startTransition: true,
  }}
/>

👉 更新您的程式碼

除非您在元件內部使用 React.lazy,否則您不需要更新任何內容。

在元件內部使用 React.lazyReact.useTransition(或其他在元件內部建立 Promise 的程式碼)不相容。將 React.lazy 移動到模組作用域,並停止在元件內部建立 Promise。這不是 React Router 的限制,而是 React 的不正確用法。

v7_fetcherPersist

如果您沒有使用 <RouterProvider>,則可以跳過此步驟

背景

Fetcher 的生命週期現在基於其返回閒置狀態的時間,而不是其擁有者元件卸載的時間:查看更新日誌以取得更多資訊。

啟用標誌

createBrowserRouter(routes, {
  future: {
    v7_fetcherPersist: true,
  },
});

更新您的程式碼

這不太可能影響您的應用程式。您可能需要檢查 useFetchers 的任何用法,因為它們的持久性可能比以前更長。根據您正在執行的操作,您可能會渲染比以前更長的時間。

v7_normalizeFormMethod

如果您沒有使用 <RouterProvider>,則可以跳過此步驟

這將 formMethod 欄位標準化為大寫 HTTP 方法,以與 fetch() 行為對齊。查看更新日誌以取得更多資訊。

👉 啟用標誌

createBrowserRouter(routes, {
  future: {
    v7_normalizeFormMethod: true,
  },
});

更新您的程式碼

如果您的任何程式碼正在檢查小寫 HTTP 方法,您將需要更新它以檢查大寫 HTTP 方法(或對其呼叫 toLowerCase())。

👉 formMethod 與大寫進行比較

-useNavigation().formMethod === "post"
-useFetcher().formMethod === "get";
+useNavigation().formMethod === "POST"
+useFetcher().formMethod === "GET";

v7_partialHydration

如果您沒有使用 <RouterProvider>,則可以跳過此步驟

這啟用了資料路由器的部分水合,主要用於 SSR 框架,但如果您使用 lazy 來載入路由模組,它也很有用。您不太可能需要擔心這個,只需開啟標誌即可。查看更新日誌以取得更多資訊。

👉 啟用標誌

createBrowserRouter(routes, {
  future: {
    v7_partialHydration: true,
  },
});

更新您的程式碼

使用部分水合時,您需要提供一個 HydrateFallback 元件以在初始水合期間渲染。此外,如果您之前使用過 fallbackElement,則需要將其移除,因為它現在已棄用。在大多數情況下,您會希望將 fallbackElement 重複用作 HydrateFallback

👉 fallbackElement 替換為 HydrateFallback

const router = createBrowserRouter(
  [
    {
      path: "/",
      Component: Layout,
+      HydrateFallback: Fallback,
      // or
+      hydrateFallbackElement: <Fallback />,
      children: [],
    },
  ],
);


<RouterProvider
  router={router}
-  fallbackElement={<Fallback />}
/>

v7_skipActionErrorRevalidation

如果您沒有使用 createBrowserRouter,則可以跳過此步驟

啟用此標誌後,在動作拋出/返回具有 4xx/5xx 狀態碼的 Response 後,載入器將不再預設重新驗證。您可以透過 shouldRevalidateactionStatus 參數選擇在這些情況下進行重新驗證。

👉 啟用標誌

createBrowserRouter(routes, {
  future: {
    v7_skipActionErrorRevalidation: true,
  },
});

更新您的程式碼

在大多數情況下,您可能不必對應用程式程式碼進行變更。通常,如果動作發生錯誤,則資料不太可能被修改且需要重新驗證。如果您的任何程式碼在動作錯誤情況下確實修改了資料,則您有 2 個選項

👉 選項 1:變更動作以避免在錯誤情況下進行修改

// Before
async function action() {
  await mutateSomeData();
  if (detectError()) {
    throw new Response(error, { status: 400 });
  }
  await mutateOtherData();
  // ...
}

// After
async function action() {
  if (detectError()) {
    throw new Response(error, { status: 400 });
  }
  // All data is now mutated after validations
  await mutateSomeData();
  await mutateOtherData();
  // ...
}

👉 選項 2:透過 shouldRevalidateactionStatus 選擇重新驗證

async function action() {
  await mutateSomeData();
  if (detectError()) {
    throw new Response(error, { status: 400 });
  }
  await mutateOtherData();
}

async function loader() { ... }

function shouldRevalidate({ actionStatus, defaultShouldRevalidate }) {
  if (actionStatus != null && actionStatus >= 400) {
    // Revalidate this loader when actions return a 4xx/5xx status
    return true;
  }
  return defaultShouldRevalidate;
}

已棄用

jsondefer 方法已被棄用,建議改為返回原始物件。

async function loader() {
- return json({ data });
+ return { data };

如果您過去使用 json 將資料序列化為 JSON,則可以改用原生 Response.json() 方法。

升級到 v7

現在您的應用程式已趕上進度,您可以簡單地更新到 v7(理論上!)而不會出現問題。

👉 安裝 v7

npm install react-router-dom@latest

👉 將 react-router-dom 替換為 react-router

在 v7 中,我們不再需要 "react-router-dom",因為套件已簡化。您可以從 "react-router" 匯入所有內容

npm uninstall react-router-dom
npm install react-router@latest

請注意,您的 package.json 中只需要 "react-router"。

👉 更新匯入

現在您應該更新您的匯入以使用 react-router

-import { useLocation } from "react-router-dom";
+import { useLocation } from "react-router";

除了手動更新匯入,您可以使用此命令。但請確保您的 git 工作樹是乾淨的,以便在它沒有如預期運作時可以還原。

find ./path/to/src \( -name "*.tsx" -o -name "*.ts" -o -name "*.js" -o -name "*.jsx" \) -type f -exec sed -i '' 's|from "react-router-dom"|from "react-router"|g' {} +

如果您已安裝 GNU sed(大多數 Linux 發行版),請改用此命令

find ./path/to/src \( -name "*.tsx" -o -name "*.ts" -o -name "*.js" -o -name "*.jsx" \) -type f -exec sed -i 's|from "react-router-dom"|from "react-router"|g' {} +

👉 更新 DOM 專用匯入

RouterProviderHydratedRouter 來自深層匯入,因為它們依賴 "react-dom"

-import { RouterProvider } from "react-router-dom";
+import { RouterProvider } from "react-router/dom";

請注意,對於非 DOM 環境(例如 Jest 測試),您應該使用頂層匯入

-import { RouterProvider } from "react-router-dom";
+import { RouterProvider } from "react-router";

恭喜,您現在已升級到 v7!

文件和範例 CC 4.0