v6からのアップグレード
このページの内容

v6からのアップグレード

すべてのfutureフラグを有効にしていれば、v7へのアップグレードに破壊的な変更はありません。これらのフラグにより、アプリを一度に1つずつ変更して更新できます。すべてを一度に行うのではなく、各手順の後にコミットして出荷することを強くお勧めします。

最新v6.xへのアップデート

まず、最新のfutureフラグとコンソール警告を取得するために、v6.xの最新のマイナーバージョンに更新します。

👉 **最新v6へのアップデート**

npm install react-router-dom@6

v7_relativeSplatPath

背景

dashboard/*(単なる*ではなく)のような複数セグメントのスプラットパスの相対パス照合とリンクを変更します。詳細については、変更履歴をご覧ください。

👉 **フラグを有効にする**

フラグの有効化は、ルーターの種類によって異なります

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

コードの更新

<Route path="dashboard/*">のようなパスとスプラットを持つルートがあり、その下に<Link to="relative"><Link to="../relative">のような相対リンクがある場合は、コードを更新する必要があります。

👉 **<Route>を2つに分割する**

複数セグメントのスプラット<Route>を、パスを持つ親ルートとスプラットを持つ子ルートに分割します

<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.useStateの代わりにReact.useTransitionを使用します。詳細については、変更履歴をご覧ください。

👉 **フラグを有効にする**

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

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

👉 **コードの更新**

コンポーネントの*内部*でReact.lazyを使用していない限り、何も更新する必要はありません。

コンポーネント内部でReact.lazyを使用することは、React.useTransition(またはコンポーネント内部でPromiseを作成する他のコード)と互換性がありません。React.lazyをモジュールスコープに移動し、コンポーネント内部でPromiseを作成しないようにしてください。これはReact Routerの制限ではなく、Reactの誤った使用方法です。

v7_fetcherPersist

<RouterProvider>を使用していない場合は、これをスキップできます

背景

フェッチャーのライフサイクルは、所有者コンポーネントがアンマウントされたときではなく、アイドル状態に戻ったときに基づくようになりました。詳細については、変更履歴をご覧ください。

フラグを有効にする

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

コードの更新

アプリに影響を与える可能性は低いです。useFetchersの使用状況を確認すると、以前よりも長く存続する可能性があります。何をしているかによっては、以前よりも長くレンダリングされる場合があります。

v7_normalizeFormMethod

<RouterProvider>を使用していない場合は、これをスキップできます

これは、fetch()の動作に合わせて、formMethodフィールドを大文字のHTTPメソッドとして正規化します。詳細については、変更履歴をご覧ください。

👉 **フラグを有効にする**

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フレームワークは部分的なハイドレーションデータのみを提供できます。これについて心配する必要はおそらくありません。フラグをオンにするだけです。詳細については、変更履歴をご覧ください。

👉 **フラグを有効にする**

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

コードの更新

部分的なハイドレーションでは、初期ハイドレーション中にレンダリングするHydrateFallbackコンポーネントを提供する必要があります。また、以前fallbackElementを使用していた場合は、非推奨になったため削除する必要があります。ほとんどの場合、fallbackElementHydrateFallbackとして再利用します。

👉 **fallbackElementHydrateFallbackに置き換える**

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:エラーシナリオでの変更を避けるためにactionを変更する**

// 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;
}

非推奨

jsonメソッドとdeferメソッドは、生のオブジェクトを返すことを推奨するため、非推奨になりました。

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";

Jestテストなどの非DOMコンテキストには、トップレベルのインポートを使用する必要があることに注意してください

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

おめでとうございます。これでv7になりました!

ドキュメントと例 CC 4.0