Claude Code React・Next.js フロントエンド開発完全ガイド|コンポーネント設計・Server Components・Server Actions・アクセシビリティ・パフォーマンス最適化の実践パターン

Claude Code React・Next.js フロントエンド開発完全ガイド|コンポーネント設計・Server Components・Server Actions・アクセシビリティ・パフォーマンス最適化の実践パターン AI開発

Claude Codeはフロントエンド開発と非常に相性がよいツールです。コンポーネントの生成・カスタムHooksの設計・アクセシビリティの自動チェック・パフォーマンス最適化の提案まで、開発サイクルの各フェーズで活用できます。

この記事ではReactとNext.js(App Router)を対象に、Claude Codeを使ったフロントエンド開発の実践パターンを解説します。テストの書き方はテスト自動化・TDD完全ガイドを、デバッグ手法はデバッグ完全ガイドを参照してください。

スポンサーリンク

CLAUDE.mdにフロントエンド規約を設定する

フロントエンドプロジェクトはコンポーネントのファイル構造・命名規則・スタイリング方針などチームごとの規約が多岐にわたります。CLAUDE.mdに規約を記載しておくと、毎回の指示が不要になります。

CLAUDE.md(Next.js + Tailwind CSS プロジェクト設定例)
## Tech Stack
- Next.js 15 (App Router)
- React 19
- TypeScript (strict mode)
- Tailwind CSS v4
- Zustand (global state)
- TanStack Query v5 (server state / data fetching)
- Zod (validation)

## Component Rules
- Use Server Components by default; add "use client" only when needed
  (event handlers, useState, useEffect, browser APIs)
- Component files: PascalCase (UserCard.tsx)
- One component per file
- Export as named export, not default export
- Props type: inline interface named `ComponentNameProps`

## File Structure
src/
  app/          ← Next.js App Router pages and layouts
  components/
    ui/         ← Reusable primitive components (Button, Input, etc.)
    features/   ← Feature-specific components
  hooks/        ← Custom hooks
  lib/          ← Utilities, helpers
  types/        ← Shared TypeScript types

## Styling
- Use Tailwind CSS utility classes
- Never use inline styles
- For complex animations, use CSS Modules alongside Tailwind
- Dark mode: use Tailwind dark: variant (not class-based)

## Testing
- Vitest + React Testing Library
- Run: npm test

Server ComponentsとClient Componentsの使い分け

Next.js App Routerでは、コンポーネントはデフォルトでServer Componentsです。"use client"が必要な場合をClaude Codeに正確に判断させるには、判断基準を事前に伝えることが重要です。

Server Component Client Component(”use client”が必要)
データフェッチ(直接DBアクセス・fetch) onClick・onChange などのイベントハンドラー
バックエンドリソースへのアクセス useState・useReducer などの状態管理
APIキーなどの機密情報へのアクセス useEffect・useLayoutEffect
大きな依存関係のバンドルサイズ削減 ブラウザ専用API(localStorage・navigator)
SEOが重要な静的コンテンツ アニメーション・ドラッグなどのインタラクション
Server/Client判断を含むコンポーネント生成
claude "Create a ProductCard component for a Next.js 15 App Router project.

The component needs to:
- Display product image, name, price, and rating
- Have an 'Add to Cart' button that calls addToCart(productId) from our
  Zustand cart store
- Show a skeleton loading state while data is loading

Decide whether this should be a Server Component or Client Component,
and explain your reasoning. Follow the conventions in CLAUDE.md."
生成されるProductCardコンポーネント例
// products/ProductCard.tsx
// "use client" が必要な理由: Zustandストアへのアクセス(ブラウザ側の状態)
"use client";

import Image from "next/image";
import { useCartStore } from "@/store/cart";

interface ProductCardProps {
  id: string;
  name: string;
  price: number;
  imageUrl: string;
  rating: number;
}

export function ProductCard({ id, name, price, imageUrl, rating }: ProductCardProps) {
  const addToCart = useCartStore((state) => state.addToCart);

  return (
    <div className="rounded-lg border border-gray-200 p-4 shadow-sm">
      <Image src={imageUrl} alt={name} width={200} height={200} className="rounded-md" />
      <h3 className="mt-2 text-lg font-semibold">{name}</h3>
      <p className="text-2xl font-bold text-blue-600">&yen;{price.toLocaleString()}</p>
      <button
        onClick={() => addToCart(id)}
        className="mt-3 w-full rounded-md bg-blue-600 px-4 py-2 text-white hover:bg-blue-700"
      >
        カートに追加
      </button>
    </div>
  );
}

カスタムHooksの設計と生成

ロジックをコンポーネントから分離するカスタムHooksは、テスタビリティと再利用性を高める重要なパターンです。Claude Codeは「何をしたいか」を伝えるだけで適切なHook設計を提案します。

カスタムHooks生成のプロンプト
claude "Create a custom hook useInfiniteScroll that:
- Observes a target element (ref) using IntersectionObserver
- Calls a provided callback function when the element enters the viewport
- Handles cleanup on unmount
- Returns isIntersecting boolean

Also create a useDebounce hook that:
- Takes a value and delay (ms)
- Returns the debounced value
- Cleans up the timer on unmount or value change

Write unit tests for both hooks using Vitest + React Testing Library."
生成されるuseDebounce Hook例
// hooks/useDebounce.ts
import { useState, useEffect } from "react";

export function useDebounce<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState<T>(value);

  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => clearTimeout(timer);
  }, [value, delay]);

  return debouncedValue;
}

TanStack QueryのカスタムHooksを生成する

TanStack Queryを使ったデータフェッチHook
claude "Create TanStack Query hooks for the products API (src/api/products.ts).
Create:
1. useProducts(filters) - GET /api/products with optional filters
2. useProduct(id) - GET /api/products/:id, disabled if id is undefined
3. useCreateProduct() - POST /api/products mutation with optimistic update
4. useUpdateProduct() - PUT /api/products/:id mutation
5. useDeleteProduct() - DELETE /api/products/:id with list cache invalidation

Use query keys as: ['products', filters], ['products', id]
For mutations, invalidate the products list on success."

Server Actions の実装

Next.js App RouterのServer Actionsは、クライアントからサーバー側の処理を直接呼び出せる機能です。フォームの送信・データの更新に使いやすく、Claude Codeはバリデーション・エラーハンドリング・再検証まで一括で生成できます。

Server Actionsの生成
claude "Create a Server Action for creating a new user profile in Next.js 15.

Requirements:
- Validate input with Zod (name: string min 2, email: valid email,
  bio: string optional max 500 chars)
- Save to database using Prisma (User model)
- Revalidate the path /profile after success
- Return a typed result: { success: true, userId: string }
  or { success: false, errors: ZodError['errors'] }
- Handle Prisma unique constraint error for duplicate email

Use 'use server' directive. Export as createUserProfile."
生成されるServer Action例
// app/actions/user.ts
"use server";

import { z } from "zod";
import { revalidatePath } from "next/cache";
import { prisma } from "@/lib/prisma";
import { Prisma } from "@prisma/client";

const CreateUserSchema = z.object({
  name: z.string().min(2, "名前は2文字以上で入力してください"),
  email: z.string().email("有効なメールアドレスを入力してください"),
  bio: z.string().max(500, "自己紹介は500文字以内で入力してください").optional(),
});

type CreateUserResult =
  | { success: true; userId: string }
  | { success: false; errors: z.ZodError["errors"] | string };

export async function createUserProfile(
  formData: FormData
): Promise<CreateUserResult> {
  const parsed = CreateUserSchema.safeParse({
    name: formData.get("name"),
    email: formData.get("email"),
    bio: formData.get("bio") || undefined,
  });

  if (!parsed.success) {
    return { success: false, errors: parsed.error.errors };
  }

  try {
    const user = await prisma.user.create({ data: parsed.data });
    revalidatePath("/profile");
    return { success: true, userId: user.id };
  } catch (error) {
    if (
      error instanceof Prisma.PrismaClientKnownRequestError &&
      error.code === "P2002"
    ) {
      return { success: false, errors: "このメールアドレスはすでに使用されています" };
    }
    throw error;
  }
}

Tailwind CSSスタイリングの効率化

デザインからTailwindコンポーネントを生成する

スクリーンショットや設計仕様を渡すと、Tailwind CSSのクラスを使ったコンポーネントを生成できます。ChromeとClaude Codeを組み合わせると実装→確認→修正のサイクルが短縮されます。

デザイン仕様からコンポーネントを生成
claude "Create a pricing card component with these specifications:
- 3 tiers: Free, Pro ($19/mo), Enterprise (custom)
- Pro tier is highlighted with a blue gradient background
- Each tier has: name, price, feature list (5 items), CTA button
- Responsive: stacked on mobile, 3 columns on desktop (md:grid-cols-3)
- Use Tailwind CSS v4 only (no custom CSS)
- CTA buttons: Free=outlined, Pro=filled blue, Enterprise=outlined dark"

既存コンポーネントのTailwindリファクタリング

インラインスタイルをTailwindに移行
claude "Convert all inline styles in src/components/ to Tailwind CSS classes.
Rules:
- Never use style={{}} props
- Map CSS properties to the closest Tailwind equivalent
- For values not in the default Tailwind scale, use arbitrary values: w-[320px]
- Preserve all existing className strings
- After conversion, visually verify nothing broke by checking
  that the Tailwind classes produce equivalent styles"

shadcn/uiコンポーネントとの連携

shadcn/uiを使ったUIコンポーネント生成
claude "Add a data table component for displaying the orders list.
Use shadcn/ui's Table component (already installed).

Requirements:
- Columns: Order ID, Customer, Status (badge), Amount, Date, Actions
- Sortable columns: Date, Amount
- Status badge colors: pending=yellow, processing=blue, shipped=green, cancelled=red
- Actions column: View, Cancel (only for pending orders)
- Pagination: 20 rows per page
- Loading state with skeleton rows

Data type: Order[] from src/types/order.ts"

アクセシビリティの自動チェックと改善

アクセシビリティ(a11y)対応は見落とされがちですが、Claude Codeはコンポーネントを読んでWCAG違反を指摘し修正できます。後から直すより、生成時に一緒に対応させるのが効率的です。

アクセシビリティの一括チェック
claude "Audit the accessibility of all components in src/components/ui/.
Check for these WCAG 2.1 AA issues:
1. Missing or incorrect aria-label on interactive elements
2. Missing alt text on images
3. Form inputs without associated labels
4. Color contrast issues (describe the class combinations, not exact hex values)
5. Keyboard navigation issues (missing tabIndex, missing onKeyDown handlers)
6. Missing role attributes on custom interactive elements
7. Missing aria-expanded, aria-controls for disclosure patterns

For each issue found, show the current code and the corrected version."
生成時にa11yを要件に含める
claude "Create an accessible modal dialog component that:
- Traps focus within the modal when open
- Returns focus to the trigger element when closed
- Can be closed with Escape key
- Has role='dialog' and aria-modal='true'
- Has aria-labelledby pointing to the modal title
- Prevents scrolling of the background content
- Accessible announce to screen readers when opened (use aria-live if needed)"

パフォーマンス最適化

不要な再レンダリングの検出と修正

Reactの不要な再レンダリングはパフォーマンス問題の主要な原因です。Claude Codeはコンポーネントツリーを読んで最適化箇所を特定できます。

再レンダリング最適化の依頼
claude "Analyze the rendering performance of src/components/features/ProductList.tsx
and its child components.

Look for:
1. Components that re-render even when their props haven't changed
   (candidates for React.memo)
2. Expensive computations not wrapped in useMemo
3. Callback functions re-created on every render (candidates for useCallback)
4. Context consumers that re-render due to unrelated state changes
5. Large lists that should use virtualization (react-virtual or similar)

For each finding, explain why it causes a performance issue and show the fix."

Next.js特有の最適化

Next.js最適化のチェックリスト実行
claude "Review the Next.js performance of this app and suggest improvements:

1. Check all <Image> usage in src/ — are width/height set? Is priority set
   for above-the-fold images? Are remote domains configured in next.config.ts?

2. Check for large client-side imports that could be Server Components

3. Check for missing Suspense boundaries around dynamic content

4. Check if any Server Components are unnecessarily marked 'use client'

5. Check if dynamic() with ssr:false is used appropriately for
   browser-only components

6. Check next.config.ts for missing optimizations
   (compress, images.formats, etc.)"

Bundle Analyzerでの依存関係調査

バンドルサイズの分析と最適化
claude "The production bundle is too large (>500KB initial JS).
Help me identify and reduce it.

1. First, set up @next/bundle-analyzer:
   - Install the package
   - Add configuration to next.config.ts

2. After analysis (I'll run it and share the output), look for:
   - Libraries imported entirely but only using small parts (moment.js, lodash)
   - Duplicate dependencies
   - Components/pages that could use dynamic imports

3. Suggest specific optimizations with expected size savings"

コンポーネントテストの自動生成

React Testing Libraryを使ったコンポーネントテストもClaude Codeが自動生成できます。ユーザー操作を模したテストを「コンポーネントと同時に生成する」習慣をつけるとテストカバレッジを維持しやすくなります。

コンポーネントと同時にテストを生成
claude "Create the LoginForm component and its tests simultaneously.

Component requirements:
- Email and password inputs with validation
- Submit button that calls onSubmit(email, password) prop
- Show loading spinner during submission (isLoading prop)
- Show error message when error prop is set
- Disable the form during loading

Tests (Vitest + React Testing Library):
- Renders all form elements
- Shows validation error for invalid email
- Shows validation error for empty password
- Calls onSubmit with correct values on valid submit
- Shows loading spinner when isLoading=true
- Disables submit button when isLoading=true
- Displays the error message when error prop is set"

よくある質問

QServer ComponentsとClient Componentsの境界線を毎回Claude Codeが正しく判断してくれません

ACLAUDE.mdに判断基準を明記するのが最も効果的です。「useStateやイベントハンドラーを使う場合は”use client”を追加。それ以外はデフォルトでServer Componentとする」のように具体的なルールを書いてください。個別のコンポーネント生成時に「Server ComponentかClient Componentかを明示して判断根拠も説明して」と付け加えると確認しながら進められます。

QTailwind CSSのクラスが長くなりすぎて管理しにくくなります

AClaude Codeに「cn()ヘルパー(clsx + tailwind-merge)を使ってクラスを整理して」と依頼すると、条件付きクラスや長いクラス列を読みやすく整理してくれます。また「このコンポーネントのスタイルをTailwind v4のCSS変数として抽出してtheme()で参照するようにして」と頼むと、デザイントークン化も対応してくれます。

QNext.js App RouterでのData Fetchingのパターンが多すぎて迷います

A「このデータはどこでフェッチすべきか判断して」と、データの性質(リアルタイム性・認証要否・キャッシュ戦略)を説明しながら依頼すると、Claude Codeが最適なパターンを提案します。具体的には:静的コンテンツはServer Component + fetch with cache→Server Component + TanStack Query→リアルタイムはWebSocket/Server-Sent Eventsという判断軸をCLAUDE.mdに書いておくと一貫性が保たれます。

Qアクセシビリティの修正をしたら見た目が崩れてしまいました

Aアクセシビリティ属性の追加(aria-label・role等)は見た目に影響しないはずです。見た目が崩れた場合はHTMLの構造変更(labelとinputの関連付けでDOMが変わった等)が原因の可能性があります。「アクセシビリティを改善したが見た目が崩れた。スタイルを変更せずにa11yのみ修正して」と依頼し直してください。

Qスクリーンショットを見せてデザイン再現を頼むことはできますか?

Aできます。Claude Codeは画像を読み取ってTailwindのコンポーネントを生成できます。ただし色・フォントサイズ・間隔の正確な数値は近い値になることがあります。FigmaのMCPサーバーを連携させると、Figmaのデザインデータから直接コンポーネントを生成できるため精度が上がります。MCPサーバーの設定はMCP完全ガイドを参照してください。