clerk-react-router-patterns について
React Router v7/v8 プロジェクト向けの Clerk 認証スキルです。ミドルウェア、ローダー、アクション、クライアントコンポーネントで認証を扱う開発者に向け、サーバーからクライアントへの認証状態の受け渡しやバージョン別設定を説明します。
主な機能
- 01ローダーとアクションでの認証
- 02ミドルウェアとルート認証状態の受け渡し
- 03保護ルートとリダイレクト
- 04クライアント認証フック
- 05React Router v7/v8 の設定案内
活用シーン
- 01ローダーでユーザー別データを取得
- 02アクション処理前にユーザーを検証
- 03ルートを保護し未認証ユーザーを転送
- 04SSR アプリでクライアントに認証状態を提供
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ clerk/ skills --skill clerk-react-router-patternsインストール後、Claude Code で/clerk-react-router-patternsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
evals/evals.jsonreferences/loaders-actions.mdprotected-routes.mdssr-auth.mdtemplates/react-router-basic-auth/package.jsonreact-router.config.tsvite.config.tstemplates/react-router-basic-auth/app/app.cssroot.tsxroutes.tstemplates/react-router-basic-auth/app/routes/home.tsx詳細
React Routerのパターン
SDK:@clerk/react-router v3.5+。React Router v7.9+およびv8に対応しています。
必要な情報を選んでください
| タスク | リファレンス |
|---|---|
| ローダーとアクションでの認証 | references/loaders-actions.md |
| 保護されたルートとリダイレクト | references/protected-routes.md |
| SSRのユーザーデータとセッション | references/ssr-auth.md |
React Router v7とv8の違い
セットアップの前に、インストールされているreact-routerのメジャーバージョンを確認してください。設定が異なります。
| v7.9+ | v8+ | |
|---|---|---|
| ミドルウェアAPI | オプトイン:react-router.config.tsでfuture: { v8_middleware: true }を設定 | 常に有効です。フラグは設定しないでください(v8では削除されています) |
ssr.noExternalの回避策(下記) | 不要 | 必須 |
最小限のセットアップ
1. vite.config.ts(v8のみ — 必須)
React Router v8には、開発環境と本番環境で異なる条件付きエクスポートが含まれています。react-router devでは、
ViteがSSR用に@clerk/react-routerを外部化するため、Nodeはreact-routerの本番ビルドを解決する一方で、
アプリのコードは開発ビルドを取得します。その結果、モジュールインスタンスとRouterコンテキストがそれぞれ2つになり、
すべてのリクエストがSSR中に次のエラーで失敗します。
Error: useNavigate() may be used only in the context of a <Router> component.
npm ls react-routerでコピーが1つだけ表示されても、問題がないとは限りません。 重複はインストールされたコピーごとではなく、エクスポート条件ごとに発生します。重複インストールを調べるのではなく、回避策を追加してください(上流のissue:
https://github.com/remix-run/react-router/issues/15232)。
import { reactRouter } from '@react-router/dev/vite'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [reactRouter()],
ssr: {
noExternal: ['@clerk/react-router'],
},
})
2. root.tsx
import { Outlet } from 'react-router'
import { rootAuthLoader, clerkMiddleware } from '@clerk/react-router/server'
import { ClerkProvider } from '@clerk/react-router'
import type { Route } from './+types/root'
export const middleware: Route.MiddlewareFunction[] = [clerkMiddleware()]
export async function loader(args: Route.LoaderArgs) {
return rootAuthLoader(args)
}
export default function App({ loaderData }: Route.ComponentProps) {
return (
<ClerkProvider loaderData={loaderData}>
<Outlet />
</ClerkProvider>
)
}
@clerk/react-routerにはClerkApp HOCはありません(これは@clerk/remixのAPIでした)。
デフォルトエクスポート内で<ClerkProvider loaderData={loaderData}>をレンダリングし、
ルートルートのloaderDataを渡してください。
3. react-router.config.ts(v7のみ)
import type { Config } from '@react-router/dev/config'
export default {
future: {
v8_middleware: true,
},
} satisfies Config
v8ではfutureブロック全体を省略してください。フラグはもう存在しません。
必須:
rootAuthLoaderはroot.tsxのloaderで呼び出す必要があります。これがないと、ネストされたloaderでgetAuthが例外をスローします。
基本的な考え方
React Router v7/v8は、ミドルウェアとローダーのパイプラインを使用します。Clerkは両方のレイヤーに組み込まれます。
- ミドルウェア(
clerkMiddleware()) — すべてのリクエストで実行され、認証情報をコンテキストに付与します rootAuthLoader— Clerkの状態をクライアントに渡すため、root.tsxで必須ですgetAuth(args)— 現在のユーザーを取得するため、任意のloader/action内で呼び出します
Request → clerkMiddleware() → rootAuthLoader → page loader → component
↓ ↓ ↓
attaches auth injects state getAuth(args)
to context to response reads context
ローダーでの認証
import { getAuth } from '@clerk/react-router/server'
import type { Route } from './+types/dashboard'
export async function loader(args: Route.LoaderArgs) {
const { userId } = await getAuth(args)
if (!userId) throw redirect('/sign-in')
const data = await fetchUserData(userId)
return { data }
}
アクションでの認証
import { getAuth } from '@clerk/react-router/server'
export async function action(args: Route.ActionArgs) {
const { userId, orgId } = await getAuth(args)
if (!userId) throw new Response('Unauthorized', { status: 401 })
const formData = await args.request.formData()
await saveData(userId, orgId, formData)
return redirect('/dashboard')
}
クライアントコンポーネント
import { useAuth, useUser } from '@clerk/react-router'
export function Profile() {
const { userId, isSignedIn } = useAuth()
const { user } = useUser()
if (!isSignedIn) return null
return <p>{user?.firstName}</p>
}
組織の切り替え
import { OrganizationSwitcher } from '@clerk/react-router'
export function Nav() {
return <OrganizationSwitcher afterSelectOrganizationUrl="/dashboard" />
}
export async function loader(args: Route.LoaderArgs) {
const { userId, orgId } = await getAuth(args)
if (!userId) throw redirect('/sign-in')
if (!orgId) throw redirect('/select-org')
return { data: await fetchOrgData(orgId) }
}
よくある問題
| 症状 | 原因 | 修正方法 |
|---|---|---|
v8の開発環境でSSR中にClerkProviderからuseNavigate() may be used only in the context of a <Router>がスローされる | Viteの開発時SSRが@clerk/react-routerを外部化するため、アプリが開発ビルドを使用する一方で、react-routerの本番ビルドが読み込まれ、Routerコンテキストが2つになります。npm lsでコピーが1つだけ表示されても、問題がないとは限りません。 | vite.config.tsにssr: { noExternal: ['@clerk/react-router'] }を追加してください。v7にダウングレードしないでください |
ビルドエラー:ClerkAppはエクスポートされていません | @clerk/react-routerにClerkAppは存在しません | root.tsxのデフォルトエクスポートで<ClerkProvider loaderData={loaderData}>を使用してください |
clerkMiddleware() not detected | ミドルウェアがありません(またはv7でv8_middlewareのfutureフラグがありません) | ルートからmiddleware = [clerkMiddleware()]をエクスポートしてください。v7ではfuture: { v8_middleware: true }も設定してください |
| 不明なfutureフラグのエラー/警告(v8) | アップグレード後もreact-router.config.tsにv8_middlewareフラグが残っています | future.v8_middlewareの項目を削除してください。v8ではミドルウェアは常に有効です |
getAuthが空のuserIdを返す | rootAuthLoaderが呼び出されていません | root.tsxのloaderでrootAuthLoader(args)を呼び出してください |
| リダイレクトが無限に繰り返される | リダイレクト先も保護されています | 保護チェックから/sign-inを除外してください |
actionでredirectが機能しない | throw redirect()ではなくResponseを使用しています | react-routerのthrow redirect('/path')を使用してください |
Import Map
| What | Import From |
|---|---|
getAuth | @clerk/react-router/server |
rootAuthLoader | @clerk/react-router/server |
clerkMiddleware | @clerk/react-router/server |
ClerkProvider | @clerk/react-router |
useAuth, useUser | @clerk/react-router |
OrganizationSwitcher | @clerk/react-router |
See Also
clerk-setup- Initial Clerk installclerk-custom-ui- Custom flows & appearanceclerk-orgs- B2B organizations