🌴

TanStack Routerでサクッと始める型安全ルーティング

2024/09/01に公開

はじめに

こんにちは。calloc134 です。

自分は普段 React を利用してフロントエンドの開発をしています。
SPA のルーティングを実装する上で、TanStack Router を利用することが多いです。

この使い方について、簡単にまとまったドキュメントが思ったより少なく感じたため、まとめていきたいと思います。

TanStack Router とは

TanStack Router は、React のルーティングを行うためのライブラリです。
当初は React Location として、TanStack の Tanner Linsley 氏によって開発されました。
https://dev.classmethod.jp/articles/intro-react-location/

その後、改名や設計のし直しが行われ、TanStack Router として開発されており、2023 年のクリスマスに v1 がリリースされました。
https://x.com/tannerlinsley/status/1738709130213560497

現在は色々な機能が追加されており、React のルーティングを行うためのライブラリとして非常に人気があります。

TanStack Router の特徴

型安全の偉大さ

TanStack Router は、なんといっても型安全性が非常に高いです。
https://tanstack.com/router/latest/docs/framework/react/guide/type-safety

TanStack Router では、リンクコンポーネントやリダイレクト時にパスを指定することができます。このとき、存在しているルーティングのパスだけを型として受け付け、補完やエラーを出すことができます。
また、動的ルートやクエリパラメータの型についても安全に扱うことができます。

始めてみる

では、実際に利用してみましょう
なお、公式ではファイルベースのルーティングを推奨していますが、今回は説明を簡単にするため、コードベースでのルーティングを行います。
また、パッケージマネージャーには pnpm を利用しています。

セットアップ

pnpm create vite tanstack-router-lab --template react-ts
cd tanstack-router-lab
pnpm install

App.tsx を適当なコンポーネントに書き換えます。

App.tsx
export const Hello = () => {
  return (
    <div>
      <h1>Hello World</h1>
      <p>Click on the links above to see the code splitting in action.</p>
    </div>
  );
};

次に、TanStack Router をインストールします。

pnpm add @tanstack/react-router

ルーティングの記述

では、main.tsxと同じディレクトリにroute.tsxを作成し、以下のように記述します。

route.tsx
import { createRootRoute, createRouter } from "@tanstack/react-router";
import { Hello } from "./App";

const rootRoute = createRootRoute({
  component: () => <Hello />,
});

const routeTree = rootRoute;

export const router = createRouter({ routeTree });

declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}

ここで、コードの解説をしていきます。

createRootRoute は、根本のルートを作成する関数です。
routeTree とは、ルーティングのツリー構造を表す変数です。今回は、rootRoute だけを指定しています。
createRouterrouteTreeを渡すことで、ルーティングを行うためのrouterが作成されます。

ここで、createRootRoute の引数に component を指定していますが、これはルートにコンポーネントを指定するためのものです。

では、main.tsxRouterProviderを追加し、ルーティングができるようにします。

main.tsx
import { RouterProvider } from "@tanstack/react-router";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { router } from "./route";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <RouterProvider router={router} />
  </StrictMode>
);

ここでは、先程作成したrouterRouterProviderに渡すことで、ルーティングが有効になります。

vite サーバを立ち上げると、Hello コンポーネントの内容が表示されるはずです。

ここの部分の内容は以下のリポジトリにあります。
https://github.com/calloc134/tanstack-router-lab

https://tanstack.com/router/latest/docs/framework/react/guide/code-based-routing

pnpm run dev

開発者ツールの追加

TanStack Router には、開発者ツールが用意されています。

このコンポーネントを追加することで、ルーティングの情報を確認することができます。

pnpm add @tanstack/router-devtools

導入後、main.tsxを以下のように修正します。

main.tsx
import { RouterProvider } from "@tanstack/react-router";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { router } from "./route";
import { TanStackRouterDevtools } from "@tanstack/router-devtools";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <RouterProvider router={router} />
    <TanStackRouterDevtools router={router} />
  </StrictMode>
);

これで、開発者ツールが表示されるようになります。
便利なので是非導入してみてください。

なお、RouterProviderの内部でTanStackRouterDevtoolsを利用する場合はrouterを渡す必要がなく、自動的に取得されます。
今回はまだRouterProvider内部でネストされたルーティングを設定していないため、RouterProviderの外でrouterを渡しています。

https://tanstack.com/router/latest/docs/framework/react/devtools

一般的なルート

一般的にはRootにコンポーネントを指定せず、Root以下に別途ルーティングを記述します。

route.tsx
import {
  createRootRoute,
  createRoute,
  createRouter,
} from "@tanstack/react-router";
import { Hello } from "./App";

const rootRoute = createRootRoute({});

const indexRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: "/",
  component: () => <Hello />,
});

const routeTree = rootRoute.addChildren([indexRoute]);

export const router = createRouter({ routeTree });

declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}

createRoute は、根本でないルートを作成する関数です。

createRouteでは、getParentRoutepathが必須となっています。
getParentRoute は、親のルートを指定する関数です。
path は、ルーティングのパスを指定します。
component には先程と同様にコンポーネントを指定します。

また、routeTree には、rootRoute に子のルートを追加したものを指定します。addChildren メソッドを利用することで、子のルートを追加することができます。

このように記述することで、/ にアクセスしたときに Hello が表示されるようになります。

https://tanstack.com/router/latest/docs/framework/react/guide/code-based-routing

リンクやリダイレクトの型安全

TanStack Router では、リンクやリダイレクトを行うためのコンポーネントが提供されています。

試しに、App.tsxにリンクを追加してみましょう。
Link コンポーネントを利用することで、リンクを作成することができます。

App.tsx
import { Link } from "@tanstack/react-router";

export const Hello = () => {
  return (
    <div>
      <h1>Hello World</h1>
      <p>Click on the links above to see the code splitting in action.</p>
      <Link to="/">Go to Home</Link>
    </div>
  );
};

すると、ルーティングに存在するパスを型として受け付け、補完が効くようになります。

また、リンクが追加されます。
/にアクセスし、リンクをクリックすると、ページが遷移することが確認できます。

https://tanstack.com/router/latest/docs/framework/react/guide/navigation#link-component

また、TanStack Router ではuseNavigateというフックも提供されています。
このフックの返すnavigate関数を利用することで、リダイレクトを行うことができます。

App.tsx
import { Link, useNavigate } from "@tanstack/react-router";

export const Hello = () => {
  const navigate = useNavigate();
  return (
    <div>
      <h1>Hello World</h1>
      にコンポーネントを指定せず、ルート以下にルーティングを別途記述します。
      <p>Click on the links above to see the code splitting in action.</p>
      <Link to="/">Go to Home</Link>
      <button
        onClick={() =>
          navigate({
            to: "/",
          })
        }
      >
        Go to Lazy
      </button>
    </div>
  );
};

navigate関数はオブジェクトを引数に取り、toプロパティにリダイレクト先のパスを指定します。
ここでも、型安全にリダイレクト先のパスを指定することができます。


/にアクセスしてボタンを押すと、リダイレクトが行われることが確認できます。

https://tanstack.com/router/latest/docs/framework/react/guide/navigation#usenavigate

クエリ文字列については複雑であるため、後から解説します。

可能なルーティングのパターン

ネストされたルート

TanStack Router では、ネストしたルートを簡単に作成することができます。

また、ネストしたルートのコンポーネント内で<Outlet>コンポーネントを利用することで、外枠となるレイアウトを簡単に実装することができます。

<Outlet>コンポーネントの使い方は、同じルーティングライブラリのreact-routerと似ています。

では、Layout.tsxを作成し、以下のように記述します。

Layout.tsx
export const Layout = ({ children }: { children: React.ReactNode }) => {
  return (
    <div>
      <header>
        <h1>I'm a header</h1>
      </header>
      {children}
    </div>
  );
};

children で受け取ったコンポーネントを表示するだけのシンプルなコンポーネントです。ヘッダが付いています。

では、route.tsxを記述してルーティングを修正します。

route.tsx
import {
  createRootRoute,
  createRoute,
  createRouter,
  Outlet,
} from "@tanstack/react-router";
import { Hello } from "./App";
import { Layout } from "./Layout";

const rootRoute = createRootRoute({
  component: () => (
    <Layout>
      <Outlet />
    </Layout>
  ),
});

const indexRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: "/",
  component: () => <Hello />,
});

const routeTree = rootRoute.addChildren([indexRoute]);

export const router = createRouter({ routeTree });

declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}

LayoutコンポーネントをrootRouteに指定し、その中に<Outlet>コンポーネントを配置しました。

これで、Layoutコンポーネントが表示されるようになります。
/にアクセスしましょう。

HelloコンポーネントがLayoutコンポーネントの中に表示されていることがわかります。

ネストされたルートの基本的な使い方としては、親のルートで外枠となるコンポーネントを指定し、children に<Outlet>コンポーネントを指定するのが好ましいでしょう。
その上で、子のルートにコンポーネントを指定することで、外枠のコンポーネントに子のコンポーネントが埋め込まれる形となります。

https://tanstack.com/router/latest/docs/framework/react/guide/outlets#the-outlet-component

これを応用して、特定のパス以下にネストされたルートを作成することも可能です。

route.tsxを以下のように修正します。

route.tsx
import {
  createRootRoute,
  createRoute,
  createRouter,
  Outlet,
} from "@tanstack/react-router";
import { Hello } from "./App";
import { Layout } from "./Layout";

const rootRoute = createRootRoute({});

const indexRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: "/hello",
  component: () => (
    <Layout>
      <Outlet />
    </Layout>
  ),
});

const helloRoute = createRoute({
  getParentRoute: () => indexRoute,
  path: "/foo",
  component: () => <Hello />,
});

const routeTree = rootRoute.addChildren([indexRoute.addChildren([helloRoute])]);

export const router = createRouter({ routeTree });

declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}

これで、/hello/fooにアクセスしたときにHelloコンポーネントが表示されるようになります。

また、/helloにアクセスしたときに、Layoutコンポーネントのヘッダが表示されるのがわかります。なお、中身については空であるため、何も表示されません。

パス無しのルート

TanStack Router では、パス無しのルートを作成することができます。
これは、ルーティングの観点からはあまり意味のない機能です。
しかし、ルーティングの構造を関心事でまとめたい場合には有用であると考えられます。

使い方としては先程のネストされたルートに似ていますが、パスを指定せず、id を指定するところが異なります。

route.tsx
import {
  createRootRoute,
  createRoute,
  createRouter,
} from "@tanstack/react-router";
const rootRoute = createRootRoute({});

const greetingRoute = createRoute({
  getParentRoute: () => rootRoute,
  id: "greeting",
});

const helloRoute = createRoute({
  getParentRoute: () => greetingRoute,
  path: "/hello",
  component: () => <p>Hello</p>,
});

const byeRoute = createRoute({
  getParentRoute: () => greetingRoute,
  path: "/bye",
  component: () => <p>Bye</p>,
});

const routeTree = rootRoute.addChildren([
  greetingRoute.addChildren([helloRoute, byeRoute]),
]);

export const router = createRouter({ routeTree });

declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}

ルーティングとしては、/hello/byeが存在しますが、これらをまとめて扱いたいものです。
この場合には、パス無しルーティングを利用することで、greetingというグループを作成し、その子ルートとして/hello/byeを追加することができます。

/helloにアクセスすると、Helloが表示されます。

/byeにアクセスすると、Byeが表示されます。

https://tanstack.com/router/latest/docs/framework/react/guide/code-based-routing#pathless-routes

動的ルートとパラメータ取得

TanStack Router では、動的ルートを作成することができます。

動的ルートとは、パスの一部を動的に変更することができるルートのことです。
パスに$から始まる変数を指定することで、動的ルートを作成することができます。
イメージとしてはワイルドカードのようなものです。

では、route.tsxを以下のように修正します。

route.tsx
import {
  createRootRoute,
  createRoute,
  createRouter,
} from "@tanstack/react-router";
import { Hello } from "./App";
const rootRoute = createRootRoute({});

const helloRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: "/$helloId",
  component: () => <Hello />,
});
const routeTree = rootRoute.addChildren([helloRoute]);

export const router = createRouter({ routeTree });

declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}

helloIdという変数を$で指定しています。

/(任意の文字列)にアクセスし、Helloが表示されることを確認します。

更に、コンポーネント内部でuseParamsフックを利用することで、パラメータを取得することができます。

App.tsx
import { useParams } from "@tanstack/react-router";

export const Hello = () => {
  const { helloId } = useParams({ from: "/$helloId" });
  return (
    <div>
      <h1>Hello World</h1>
      <p>Click on the links above to see the code splitting in action.</p>
      <p>
        The current helloId is: <strong>{helloId}</strong>
      </p>
    </div>
  );
};

useParamsフックは、オブジェクトを引数に取り、fromプロパティに現在のパスを指定します。

では、/(任意の文字列)にアクセスし、パラメータが表示されることを確認します。

正常にパラメータが取得できていることが確認できます。

https://tanstack.com/router/latest/docs/framework/react/guide/code-based-routing#dynamic-route-segments

コンポーネントの指定

TanStack Router では、いくつかの特徴的なコンポーネントが指定できます。

今までの例では、componentプロパティにコンポーネントを指定していました。
これ以外にも、ルートにおいて指定できるコンポーネントが存在します。

Not Found コンポーネント

存在しないルートであったときに表示されるコンポーネントです。
親のルートか、一番上のルートに指定します。
今回は、一番上のrootRouteに指定します。

route.tsxを以下のように修正します。

route.tsx
import {
  createRootRoute,
  createRoute,
  createRouter,
} from "@tanstack/react-router";
import { Hello } from "./App";
const rootRoute = createRootRoute({
  notFoundComponent: () => <div>Not Found... sorry</div>,
});

const helloRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: "/hello",
  component: () => <Hello />,
});
const routeTree = rootRoute.addChildren([helloRoute]);

export const router = createRouter({ routeTree });

declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}

では、/hello以外のパスにアクセスしてみましょう。

このように、存在しないパスにアクセスしたときにNot Found... sorryが表示されることが確認できます。

https://tanstack.com/router/latest/docs/framework/react/api/router/RouteOptionsType#notfoundcomponent-property

エラーコンポーネント

通常コンポーネントがエラーを起こしたときに表示されるコンポーネントです。

App.tsxにエラーを起こす処理を追加します。

App.tsx
export const Hello = () => {
  // ランダムでエラーを発生させる
  if (Math.random() > 0.5) {
    throw new Error("Random error");
  }

  return (
    <div>
      <h1>Hello World</h1>
      <p>Click on the links above to see the code splitting in action.</p>
    </div>
  );
};

route.tsxを以下のように修正します。

route.tsx
import {
  createRootRoute,
  createRoute,
  createRouter,
} from "@tanstack/react-router";
import { Hello } from "./App";
const rootRoute = createRootRoute({
  notFoundComponent: () => <div>Not Found... sorry</div>,
});

const helloRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: "/hello",
  component: () => <Hello />,
  errorComponent: () => <div>There was an error!! Sorry</div>,
});
const routeTree = rootRoute.addChildren([helloRoute]);

export const router = createRouter({ routeTree });

declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}

では、/helloにアクセスしてみましょう。

50%の確率で、正常なコンポーネントが表示されることが確認できます。

エラーが発生したときに、There was an error!! Sorryが表示されることが確認できます。

指定したエラーコンポーネントが表示されることが確認できます。

https://tanstack.com/router/latest/docs/framework/react/api/router/RouteOptionsType#errorcomponent-property

Pending コンポーネント

Pending コンポーネントは、通常コンポーネントが読み込まれるまで表示されるコンポーネントです。

これを解説する前に、React のサスペンドと Suspense コンポーネントについて簡単に説明します。

React コンポーネント内部で初期データの取得などを行う場合、データが取得されるまでコンポーネントを「ローディング中なのでレンダリングできない」という状態にすることができます。
この状態をサスペンドといいますが、この状態ではコンポーネントを表示できません。

そのため、このような状態になりうるコンポーネントをラップし、中身のコンポーネントがサスペンド状態である場合に別のコンポーネントを表示させることができるラッパーとなってくれるコンポーネントがSuspenseです。

https://zenn.dev/uhyo/books/react-concurrent-handson/viewer/what-is-suspense

<Suspense fallback={<div>サスペンドしたらこれが表示される</div>}>
  {/* ↓サスペンドしなかったらこれが表示される */}
  <MyComponent />
</Suspense>

TanStack Router では、Pending コンポーネントを指定することで、自前で Suspense コンポーネントをラップすることなく、サスペンドしたら表示されるコンポーネントを指定することができます。
したがって、サスペンドなコンポーネントをより簡単に利用することができるのです。

試しに、データ取得を非同期で行う実装で試してみましょう。

データ取得を支援する実装として、TanStack Query を利用します。
データの取得は fetch 関数で行うのですが、その間にコンポーネントをサスペンドさせることができます。

pnpm add @tanstack/react-query

まず TanStack Query を初期化するため、main.tsxに以下のように記述します。

main.tsx
import { RouterProvider } from "@tanstack/react-router";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { router } from "./route";
import { TanStackRouterDevtools } from "@tanstack/router-devtools";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

const queryClient = new QueryClient();

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <QueryClientProvider client={queryClient}>
      <RouterProvider router={router} />
      <TanStackRouterDevtools router={router} />
    </QueryClientProvider>
  </StrictMode>
);

次に、App.tsxを以下のように修正します。

App.tsx
import { useSuspenseQuery } from "@tanstack/react-query";

export const Hello = () => {
  // 3秒遅延して返却されるエンドポイントを叩いてみる
  const { data } = useSuspenseQuery({
    queryKey: ["hello"],
    queryFn: async () => {
      const response = await fetch("https://httpbin.org/delay/3");
      return response.json();
    },
  });

  return (
    <div>
      <h1>Hello World</h1>
      <p>Click on the links above to see the code splitting in action.</p>
      <p>{JSON.stringify(data)}</p>
    </div>
  );
};

useSuspenseQueryフックを利用することで、非同期処理を行い、データの取得中にコンポーネントをサスペンドすることができます。
https://httpbin.org/delay/3とは、3 秒遅延してデータを返却するエンドポイントです。

最後に、route.tsxを以下のように修正します。

route.tsx
import {
  createRootRoute,
  createRoute,
  createRouter,
} from "@tanstack/react-router";
import { Hello } from "./App";
const rootRoute = createRootRoute({
  notFoundComponent: () => <div>Not Found... sorry</div>,
});

const helloRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: "/hello",
  component: () => <Hello />,
  pendingComponent: () => <div>Loading...Please wait</div>,
  errorComponent: () => <div>There was an error!! Sorry</div>,
});
const routeTree = rootRoute.addChildren([helloRoute]);

export const router = createRouter({ routeTree });

declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}

pendingComponentプロパティに、データ取得中に表示されるコンポーネントを指定します。

では、/helloにアクセスしてみましょう。

Loading...Please waitが表示されることが確認できます。

3 秒後にデータが取得され、表示されることが確認できます。

https://tanstack.com/router/latest/docs/framework/react/api/router/RouteOptionsType#pendingcomponent-property

公式が提供しているその他の機能

クエリパラメータとバリデーション

TanStack Router では、クエリパラメータを取得することができます。
ドキュメントでは、search paramsと呼ばれています。

では、main.tsxを以下のように修正します。

main.tsx
import {
  createRootRoute,
  createRoute,
  createRouter,
} from "@tanstack/react-router";
import { Hello } from "./App";
const rootRoute = createRootRoute();

const helloRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: "/hello",
  component: () => <Hello />,
  validateSearch: (search: Record<string, unknown>) => {
    return {
      hoge: search.hoge as string,
    };
  },
});
const routeTree = rootRoute.addChildren([helloRoute]);

export const router = createRouter({ routeTree });

declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}

validateSearchプロパティには、クエリパラメータをバリデーションする関数を指定します。
この関数は引数として連想配列を受け取ります。キーはstring、値はunknownです。
クエリはhoge=fugaのようにkey=valueの形式で渡されるため、search.hogeとして取得することができます。

この値は undefined である可能性や、型として不適切な値が渡される可能性があるため、適切な型に変換する必要があります。
したがって、バリデーションを行う関数が必要になるのです。
この例では、as stringを行なって無理やり型を変換していますが、実際には適切なバリデーションを行う必要があります。

では、App.tsxを以下のように修正します。

App.tsx
import { useSearch } from "@tanstack/react-router";

export const Hello = () => {
  const { hoge } = useSearch({ from: "/hello" });

  return (
    <div>
      <h1>Hello World</h1>
      <p>Click on the links above to see the code splitting in action.</p>
      <p> hoge: {hoge}</p>
    </div>
  );
};

useSearchフックを利用することで、クエリパラメータを取得することができます。

ここで、フックの戻り値は、validateSearch関数で指定した型となっていることがわかります。

では、実際にアクセスしてみましょう。
今回は/hello?hoge=fugaにアクセスしてみます。

正常にクエリパラメータが取得できていることが確認できます。

応用として、バリデーションライブラリを利用してみましょう。

今回は、valibot を利用します。

pnpm add valibot

main.tsxを以下のように修正します。

main.tsx
import {
  createRootRoute,
  createRoute,
  createRouter,
} from "@tanstack/react-router";
import { Hello } from "./App";
import { number, object, parse } from "valibot";
const rootRoute = createRootRoute();

const querySchema = object({
  hoge: number(),
});

const helloRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: "/hello",
  component: () => <Hello />,
  validateSearch: (search: Record<string, unknown>) => {
    return parse(querySchema, search);
  },
});
const routeTree = rootRoute.addChildren([helloRoute]);

export const router = createRouter({ routeTree });

declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}

こうすることで、valibot によるバリデーションが行われるようになります。

useSearchフックの型も変更され、バリデーションの解析後の型が返されるようになります。

https://tanstack.com/router/latest/docs/framework/react/guide/search-params

遅延読み込みで効率化

TanStack Router では、初期状態で読み込まなくて良いオプションを遅延読み込みすることができます。
これにより、初期読み込みを軽減することができ、パフォーマンスの向上につながります。

ここでは、一般的なルートに対する遅延読み込みを行ってみます。

まず、遅延読み込みしたいルートについて、別途ファイルとして切り出します。
ここでは、IndexLazyRoute.tsx として切り出します。

IndexLazyRoute.tsx
import { createLazyRoute } from "@tanstack/react-router";
import { Hello } from "./App";

export const indexLazyRoute = createLazyRoute("/")({
  component: () => <Hello />,
});

このようにして、遅延読み込みされるルート(以下、遅延ルート)を作成します。

次に、route.tsx に以下のように記述します。

route.tsx
import {
  createRootRoute,
  createRoute,
  createRouter,
} from "@tanstack/react-router";

const rootRoute = createRootRoute({});

const indexRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: "/",
}).lazy(() => import("./IndexLazyRoute").then((d) => d.IndexLazyRoute));

const routeTree = rootRoute.addChildren([indexRoute]);

export const router = createRouter({ routeTree });

declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}

これで、/ にアクセスしたときに Hello が表示されるようになります。
ここでは初期ページであるためコンポーネントはすぐ読み込みされ、遅延の効果は感じられません。
しかし、初期ページ以外のページに適用することでパフォーマンスの向上が期待できます。

createLazyRoute は、遅延読み込みするための関数です。
ルーティングパスを指定して遅延読み込みするためのオプションをここに記述することにより、オプションの遅延読み込みが可能です。
通常ルートからlazyメソッドを呼び出し、遅延読み込みするファイルを指定することで、遅延読み込みを行うことができます。

では、どのようなオプションは遅延するべきなのでしょうか?

公式ドキュメントでは、遅延するべきものを以下のように定義しています。

  • 通常コンポーネント
  • Pending コンポーネント
  • エラーコンポーネント
  • Not Found コンポーネント

つまり、コンポーネントは遅延読み込みするべきだ、ということです。
詳しくは、以下のリンクを参照してください。

まとめ

今回は、TanStack Router の使い方について簡単にまとめてみました。

公式ドキュメントには、さらに多くの機能が提供されています。

  • ファイルベースルーティング
  • SSR
  • ローダー

興味がある方は、公式ドキュメントを参照してみてください。

https://tanstack.com/router/v1

では、最後まで読んでいただきありがとうございました。

GitHubで編集を提案

Discussion