TanStack Start
TanStack StartのプロジェクトにYamada UIをインストールして使用するためのガイド。
インストール
- 1
アプリケーションを作成する
TanStack Startのアプリケーションを作成します。
pnpm create @tanstack/start my-appnpx create @tanstack/start my-appyarn create @tanstack/start my-appbun create @tanstack/start my-app - 2
セットアップする
コマンドを実行すると、プロジェクトに必要なファイルやフォルダが作成されます。
pnpm dlx @yamada-ui/cli initnpx @yamada-ui/cli inityarn dlx @yamada-ui/cli initbunx @yamada-ui/cli init - 3
パッケージをインストールする
アプリケーションに
@workspaces/uiをインストールします。pnpm add "@workspaces/ui@workspace:*"npm install "@workspaces/ui@workspace:*"yarn add "@workspaces/ui@workspace:*"bun add "@workspaces/ui@workspace:*" - 4
プロバイダーを追加する
インストール後、アプリケーションのルートに
UIProviderを追加します。 ハイドレーションエラーを抑制するために、htmlとbodyにsuppressHydrationWarningをtrueに設定します。__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
カラーモードを使用する場合は、正常に動作させるためにbodyにColorModeScriptを追加する必要があります。
理由は、カラーモードがlocalStorageやcookiesを用いて実装されており、ページの読み込み時に同期を正しく機能させるためです。
__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を変更した場合は、ColorModeScriptにdefaultValueを設定します。
__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
テーマの切り替えを使用する場合は、正常に動作させるためにbodyにThemeSchemeScriptを追加する必要があります。
理由は、テーマの切り替えがlocalStorageやcookiesを用いて実装されており、ページの読み込み時に同期を正しく機能させるためです。
__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を変更した場合は、ThemeSchemeScriptにdefaultValueを設定します。
__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のコンポーネントを統合することができます。
Link
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} />
}