TanStack Start

TanStack StartのプロジェクトにYamada UIをインストールして使用するためのガイド。

インストール

  • 1

    アプリケーションを作成する

    TanStack Startのアプリケーションを作成します。

    pnpm create @tanstack/start my-app
    
  • 2

    セットアップする

    コマンドを実行すると、プロジェクトに必要なファイルやフォルダが作成されます。

    pnpm dlx @yamada-ui/cli init
    
  • 3

    パッケージをインストールする

    アプリケーションに@workspaces/uiをインストールします。

    pnpm add "@workspaces/ui@workspace:*"
    
  • 4

    プロバイダーを追加する

    インストール後、アプリケーションのルートにUIProviderを追加します。 ハイドレーションエラーを抑制するために、htmlbodysuppressHydrationWarningtrueに設定します。

    __root.tsx

    import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router"
    import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools"
    import { TanStackDevtools } from "@tanstack/react-devtools"
    import { UIProvider } from "@workspaces/ui"
    
    export const Route = createRootRoute({
      head: () => ({
        meta: [
          { charSet: "utf-8" },
          { name: "viewport", content: "width=device-width, initial-scale=1" },
          { title: "TanStack Start Starter" },
        ],
      }),
      shellComponent: RootDocument,
    })
    
    function RootDocument({ children }: { children: React.ReactNode }) {
      return (
        <html lang="en" suppressHydrationWarning>
          <head>
            <HeadContent />
          </head>
          <body suppressHydrationWarning>
            <UIProvider>{children}</UIProvider>
            <TanStackDevtools
              config={{ position: "bottom-right" }}
              plugins={[
                {
                  name: "Tanstack Router",
                  render: <TanStackRouterDevtoolsPanel />,
                },
              ]}
            />
            <Scripts />
          </body>
        </html>
      )
    }
    
  • 5

    コンポーネントを使用する

    UIProviderを追加したら、アプリケーション内でコンポーネントを使用します。

    index.tsx

    import { createFileRoute } from "@tanstack/react-router"
    import { Button } from "@workspaces/ui"
    
    export const Route = createFileRoute("/")({ component: App })
    
    function App() {
      return <Button>Click me!</Button>
    }
    

    これで、Yamada UIのセットアップは完了です!

スクリプト

ColorModeScript

カラーモードを使用する場合は、正常に動作させるためにbodyColorModeScriptを追加する必要があります。

理由は、カラーモードがlocalStoragecookiesを用いて実装されており、ページの読み込み時に同期を正しく機能させるためです。

__root.tsx

import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router"
import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools"
import { TanStackDevtools } from "@tanstack/react-devtools"
import { ColorModeScript, UIProvider } from "@workspaces/ui"
import { createServerFn } from "@tanstack/react-start"
import { getRequestHeader } from "@tanstack/react-start/server"

const getCookie = createServerFn({ method: "GET" }).handler(async () => {
  return getRequestHeader("cookie") ?? ""
})

export const Route = createRootRoute({
  loader: async () => ({
    cookie: await getCookie(),
  }),
  head: () => ({
    meta: [
      { charSet: "utf-8" },
      { name: "viewport", content: "width=device-width, initial-scale=1" },
      { title: "TanStack Start Starter" },
    ],
  }),
  shellComponent: RootDocument,
})

function RootDocument({ children }: { children: React.ReactNode }) {
  const { cookie } = Route.useLoaderData()

  return (
    <html lang="en" suppressHydrationWarning>
      <head>
        <HeadContent />
      </head>
      <body suppressHydrationWarning>
        <ColorModeScript type="cookie" />

        <UIProvider cookie={cookie}>{children}</UIProvider>
        <TanStackDevtools
          config={{ position: "bottom-right" }}
          plugins={[
            {
              name: "Tanstack Router",
              render: <TanStackRouterDevtoolsPanel />,
            },
          ]}
        />
        <Scripts />
      </body>
    </html>
  )
}

もし、コンフィグdefaultColorModeを変更した場合は、ColorModeScriptdefaultValueを設定します。

__root.tsx

import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router"
import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools"
import { TanStackDevtools } from "@tanstack/react-devtools"
import { ColorModeScript, UIProvider } from "@workspaces/ui"
import { createServerFn } from "@tanstack/react-start"
import { getRequestHeader } from "@tanstack/react-start/server"
import { config } from "@workspaces/theme"

const getCookie = createServerFn({ method: "GET" }).handler(async () => {
  return getRequestHeader("cookie") ?? ""
})

export const Route = createRootRoute({
  loader: async () => ({
    cookie: await getCookie(),
  }),
  head: () => ({
    meta: [
      { charSet: "utf-8" },
      { name: "viewport", content: "width=device-width, initial-scale=1" },
      { title: "TanStack Start Starter" },
    ],
  }),
  shellComponent: RootDocument,
})

function RootDocument({ children }: { children: React.ReactNode }) {
  const { cookie } = Route.useLoaderData()

  return (
    <html lang="en" suppressHydrationWarning>
      <head>
        <HeadContent />
      </head>
      <body suppressHydrationWarning>
        <ColorModeScript type="cookie" defaultValue={config.defaultColorMode} />

        <UIProvider config={config} cookie={cookie}>
          {children}
        </UIProvider>
        <TanStackDevtools
          config={{ position: "bottom-right" }}
          plugins={[
            {
              name: "Tanstack Router",
              render: <TanStackRouterDevtoolsPanel />,
            },
          ]}
        />
        <Scripts />
      </body>
    </html>
  )
}

ThemeSchemeScript

テーマの切り替えを使用する場合は、正常に動作させるためにbodyThemeSchemeScriptを追加する必要があります。

理由は、テーマの切り替えがlocalStoragecookiesを用いて実装されており、ページの読み込み時に同期を正しく機能させるためです。

__root.tsx

import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router"
import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools"
import { TanStackDevtools } from "@tanstack/react-devtools"
import { ThemeSchemeScript, UIProvider } from "@workspaces/ui"
import { createServerFn } from "@tanstack/react-start"
import { getRequestHeader } from "@tanstack/react-start/server"

const getCookie = createServerFn({ method: "GET" }).handler(async () => {
  return getRequestHeader("cookie") ?? ""
})

export const Route = createRootRoute({
  loader: async () => ({
    cookie: await getCookie(),
  }),
  head: () => ({
    meta: [
      { charSet: "utf-8" },
      { name: "viewport", content: "width=device-width, initial-scale=1" },
      { title: "TanStack Start Starter" },
    ],
  }),
  shellComponent: RootDocument,
})

function RootDocument({ children }: { children: React.ReactNode }) {
  const { cookie } = Route.useLoaderData()

  return (
    <html lang="en" suppressHydrationWarning>
      <head>
        <HeadContent />
      </head>
      <body suppressHydrationWarning>
        <ThemeSchemeScript type="cookie" />

        <UIProvider cookie={cookie}>{children}</UIProvider>
        <TanStackDevtools
          config={{ position: "bottom-right" }}
          plugins={[
            {
              name: "Tanstack Router",
              render: <TanStackRouterDevtoolsPanel />,
            },
          ]}
        />
        <Scripts />
      </body>
    </html>
  )
}

もし、コンフィグdefaultThemeSchemeを変更した場合は、ThemeSchemeScriptdefaultValueを設定します。

__root.tsx

import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router"
import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools"
import { TanStackDevtools } from "@tanstack/react-devtools"
import { ThemeSchemeScript, UIProvider } from "@workspaces/ui"
import { createServerFn } from "@tanstack/react-start"
import { getRequestHeader } from "@tanstack/react-start/server"
import { config } from "@workspaces/theme"

const getCookie = createServerFn({ method: "GET" }).handler(async () => {
  return getRequestHeader("cookie") ?? ""
})

export const Route = createRootRoute({
  loader: async () => ({
    cookie: await getCookie(),
  }),
  head: () => ({
    meta: [
      { charSet: "utf-8" },
      { name: "viewport", content: "width=device-width, initial-scale=1" },
      { title: "TanStack Start Starter" },
    ],
  }),
  shellComponent: RootDocument,
})

function RootDocument({ children }: { children: React.ReactNode }) {
  const { cookie } = Route.useLoaderData()

  return (
    <html lang="en" suppressHydrationWarning>
      <head>
        <HeadContent />
      </head>
      <body suppressHydrationWarning>
        <ThemeSchemeScript
          type="cookie"
          defaultValue={config.defaultThemeScheme}
        />

        <UIProvider config={config} cookie={cookie}>
          {children}
        </UIProvider>
        <TanStackDevtools
          config={{ position: "bottom-right" }}
          plugins={[
            {
              name: "Tanstack Router",
              render: <TanStackRouterDevtoolsPanel />,
            },
          ]}
        />
        <Scripts />
      </body>
    </html>
  )
}

コンポーネントの統合

TanStack StartのLinkなどのコンポーネントとYamada UIのコンポーネントを統合することができます。

import type { LinkComponent } from "@tanstack/react-router"
import { createLink } from "@tanstack/react-router"
import { Button, IconButton, Link } from "@workspaces/ui"

const CreatedLink = createLink(Link)

export const RouterLink: LinkComponent<typeof CreatedLink> = (props) => {
  return <CreatedLink {...props} />
}

const CreatedLinkButton = createLink(Button)

export const RouterLinkButton: LinkComponent<typeof CreatedLinkButton> = (
  props,
) => {
  return <CreatedLinkButton {...props} />
}

const CreatedLinkIconButton = createLink(IconButton)

export const RouterLinkIconButton: LinkComponent<
  typeof CreatedLinkIconButton
> = (props) => {
  return <CreatedLinkIconButton {...props} />
}