📚 初心者から実践活用まで完全網羅 — ClaudeCodeを今日から使いこなせる

実践活用術

ClaudeCodeでReactアプリを開発する方法【ToDoアプリで実践】

ClaudeCodeを使ってReactアプリを開発する手順を、ToDoアプリの作成を通して徹底解説します。環境構築からコンポーネント設計、状態管理、デプロイまで初心者でも実践できる内容です。

2026-05-11·約19分で読める·#ClaudeCode#React#JavaScript
[ Advertisement ]

ClaudeCodeでReactアプリを開発する方法【ToDoアプリで実践】

「Reactでアプリを作ってみたいけれど、何から始めればいいのか分からない」「JSXやuseStateの書き方を覚えるのが大変」と感じている方は多いはずです。そんな悩みを一気に解決してくれるのがClaudeCodeです。自然言語で指示を出すだけで、Reactのプロジェクト作成からコンポーネント実装、デプロイまでを自動で進めてくれます。本記事では、ClaudeCodeを使って実際にToDoアプリを完成させるまでの流れを、プロンプト例とコードサンプルを交えながら丁寧に解説します。プログラミング未経験の方でも、この記事を読み終える頃には自分の手でReactアプリを動かせるようになっているはずです。

結論:ClaudeCodeを使えばReactアプリは半日で作れる

ClaudeCodeを使えば、Reactアプリの開発は驚くほど簡単になります。従来のように公式ドキュメントとにらめっこしながらコマンドを打ち込んだり、StackOverflowで延々とエラーの解決方法を探したりする必要はありません。「ToDoアプリを作って」と指示するだけで、必要なファイル構成を提案し、Viteでプロジェクトを立ち上げ、コンポーネントを分割し、useStateやuseEffectを使った状態管理コードまで自動で書き上げてくれます。

具体的にできることは次の通りです。第一に、Node.jsやnpmの環境チェックから始まり、不足しているツールがあればインストール手順を案内してくれます。第二に、create-vitecreate-react-appを使ったプロジェクト初期化を自動で行います。第三に、UI設計を相談しながら進められるため、コンポーネント分割の最適解を一緒に考えられます。第四に、CSSやTailwindの導入、API連携、ローカルストレージへの保存、テストコードの作成までワンストップで対応してくれます。最後に、VercelやCloudflare Pagesへのデプロイ手順も具体的なコマンド付きで教えてくれます。本記事ではこの流れを、ToDoアプリという王道テーマに沿って体験していきます。

h2-1. ClaudeCodeでReact開発を始める前の準備

まずは開発環境を整えましょう。ClaudeCodeを使う場合でも、ローカルマシンに最低限のツールは必要です。具体的にはNode.js(推奨バージョンは20以上)、npmまたはpnpm、Gitの3点です。MacであればHomebrew、WindowsであればWingetを使うとスムーズにインストールできます。

ClaudeCode自体のインストールは、ターミナルで次のコマンドを実行するだけです。

npm install -g @anthropic-ai/claude-code

インストールが完了したら、作業フォルダを作ってclaudeコマンドを起動します。

mkdir todo-app && cd todo-app
claude

起動するとClaudeCodeの対話画面に入ります。ここから自然言語で指示を出していきます。最初のプロンプト例はこちらです。

プロンプト例1:「このフォルダでReactのToDoアプリを作りたいです。Viteを使ってTypeScript構成で初期化してください。」

このように依頼すると、ClaudeCodeは現在のフォルダ状態を確認したうえで、Viteのテンプレートを使ってプロジェクトを生成してくれます。途中で「TailwindCSSを入れますか?」「ESLintとPrettierを設定しますか?」といった確認が入ることもあるので、その都度回答すればOKです。

h2-2. プロジェクトの初期構成を理解する

ClaudeCodeが作成したプロジェクトは、典型的には次のような構成になります。

todo-app/
├── public/
├── src/
│   ├── components/
│   ├── hooks/
│   ├── types/
│   ├── App.tsx
│   ├── main.tsx
│   └── index.css
├── package.json
├── tsconfig.json
└── vite.config.ts

src/componentsにはコンポーネントを置き、src/hooksにはカスタムフックを格納します。型定義はsrc/typesにまとめると保守性が上がります。ClaudeCodeは初期段階でこうしたディレクトリ構造を提案してくれるため、自分で考える必要がありません。

ここで重要なのは、ClaudeCodeに「なぜこの構成にしたのか」を質問する習慣を持つことです。

プロンプト例2:「componentsとhooksを分けた理由を教えてください。初心者にも分かるように説明してください。」

このように聞くと、関心の分離(Separation of Concerns)の考え方や、ロジックとUIを分けることのメリットを丁寧に説明してくれます。ClaudeCodeは単なるコード生成ツールではなく、優秀な家庭教師としても機能します。

h2-3. ToDoアプリのコンポーネント設計

ToDoアプリは見た目こそシンプルですが、設計を考えるうえで学べることが豊富にあります。最小構成では次の3つのコンポーネントに分けるのが一般的です。

  1. TodoInput:新しいタスクを入力するフォーム
  2. TodoList:タスクの一覧を表示するリスト
  3. TodoItem:個別のタスクを表示する行

これらをClaudeCodeに作ってもらうには、次のように指示します。

プロンプト例3:「TodoInput、TodoList、TodoItemの3つのコンポーネントをsrc/components配下に作成してください。型はTypeScriptで、Todo型は{ id: string, text: string, completed: boolean }とします。」

実際に生成されるコードはこのような形になります。

// src/types/todo.ts
export type Todo = {
  id: string;
  text: string;
  completed: boolean;
};
// src/components/TodoInput.tsx
import { useState } from 'react';

type Props = {
  onAdd: (text: string) => void;
};

export function TodoInput({ onAdd }: Props) {
  const [text, setText] = useState('');

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (!text.trim()) return;
    onAdd(text.trim());
    setText('');
  };

  return (
    <form onSubmit={handleSubmit} className="flex gap-2">
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="新しいタスクを入力"
        className="flex-1 border rounded px-3 py-2"
      />
      <button type="submit" className="bg-blue-500 text-white px-4 py-2 rounded">
        追加
      </button>
    </form>
  );
}
// src/components/TodoItem.tsx
import type { Todo } from '../types/todo';

type Props = {
  todo: Todo;
  onToggle: (id: string) => void;
  onDelete: (id: string) => void;
};

export function TodoItem({ todo, onToggle, onDelete }: Props) {
  return (
    <li className="flex items-center gap-2 py-2 border-b">
      <input
        type="checkbox"
        checked={todo.completed}
        onChange={() => onToggle(todo.id)}
      />
      <span className={todo.completed ? 'line-through text-gray-400 flex-1' : 'flex-1'}>
        {todo.text}
      </span>
      <button
        onClick={() => onDelete(todo.id)}
        className="text-red-500 hover:underline"
      >
        削除
      </button>
    </li>
  );
}
// src/components/TodoList.tsx
import type { Todo } from '../types/todo';
import { TodoItem } from './TodoItem';

type Props = {
  todos: Todo[];
  onToggle: (id: string) => void;
  onDelete: (id: string) => void;
};

export function TodoList({ todos, onToggle, onDelete }: Props) {
  if (todos.length === 0) {
    return <p className="text-gray-500 text-center py-8">タスクはまだありません</p>;
  }
  return (
    <ul>
      {todos.map((todo) => (
        <TodoItem key={todo.id} todo={todo} onToggle={onToggle} onDelete={onDelete} />
      ))}
    </ul>
  );
}

このように、コンポーネントごとに役割が明確に分かれており、プロップスを通じてデータと関数を渡す構造になっています。Reactらしい設計の基本がそのまま反映されています。

h2-4. 状態管理:useStateとカスタムフック

ToDoアプリの心臓部となるのが状態管理です。シンプルなアプリではuseStateで十分ですが、ロジックを再利用しやすくするためにカスタムフックに切り出すのがおすすめです。

プロンプト例4:「ToDoの追加・削除・完了切り替えのロジックをuseTodosというカスタムフックにまとめてください。LocalStorageへの永続化も含めてください。」

このプロンプトで生成されるコードはこちらです。

// src/hooks/useTodos.ts
import { useState, useEffect } from 'react';
import type { Todo } from '../types/todo';

const STORAGE_KEY = 'todos';

export function useTodos() {
  const [todos, setTodos] = useState<Todo[]>(() => {
    const saved = localStorage.getItem(STORAGE_KEY);
    return saved ? JSON.parse(saved) : [];
  });

  useEffect(() => {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(todos));
  }, [todos]);

  const addTodo = (text: string) => {
    const newTodo: Todo = {
      id: crypto.randomUUID(),
      text,
      completed: false,
    };
    setTodos((prev) => [...prev, newTodo]);
  };

  const toggleTodo = (id: string) => {
    setTodos((prev) =>
      prev.map((todo) =>
        todo.id === id ? { ...todo, completed: !todo.completed } : todo
      )
    );
  };

  const deleteTodo = (id: string) => {
    setTodos((prev) => prev.filter((todo) => todo.id !== id));
  };

  return { todos, addTodo, toggleTodo, deleteTodo };
}

そしてApp.tsxではこのフックを呼び出すだけです。

// src/App.tsx
import { TodoInput } from './components/TodoInput';
import { TodoList } from './components/TodoList';
import { useTodos } from './hooks/useTodos';

function App() {
  const { todos, addTodo, toggleTodo, deleteTodo } = useTodos();

  return (
    <div className="max-w-xl mx-auto p-6">
      <h1 className="text-2xl font-bold mb-4">ToDoアプリ</h1>
      <TodoInput onAdd={addTodo} />
      <TodoList todos={todos} onToggle={toggleTodo} onDelete={deleteTodo} />
    </div>
  );
}

export default App;

カスタムフックに分離することで、App.tsxは「画面の組み立て」に集中でき、ロジックは独立してテストできるようになります。これはReact開発の重要な作法のひとつです。

h2-5. スタイリングとUIの磨き込み

機能が完成したら次は見た目です。本記事ではTailwindCSSを使う前提で進めていますが、CSSモジュールやstyled-componentsも選択肢になります。ClaudeCodeに「UIをモダンにして」と頼むと驚くほど洗練されたデザインを提案してくれます。

プロンプト例5:「ToDoアプリの見た目を、ダークモード対応のミニマルなデザインに変更してください。完了したタスクは薄く表示し、ホバーエフェクトも追加してください。」

すると次のような調整が入ります。

// src/App.tsx(抜粋)
<div className="min-h-screen bg-gray-50 dark:bg-gray-900 transition-colors">
  <div className="max-w-xl mx-auto p-6">
    <h1 className="text-3xl font-bold mb-6 text-gray-800 dark:text-gray-100">
      My ToDo
    </h1>
    {/* ... */}
  </div>
</div>

ダークモードはTailwindのdark:プレフィックスを使うのが定番です。OSのカラースキームに合わせるためにはtailwind.config.jsdarkMode: 'media'を指定します。ユーザーがトグルで切り替えられるようにしたい場合はdarkMode: 'class'を選び、ボタンで<html>にクラスを付け外しする仕組みを実装します。

[ Advertisement ]

h2-6. 実践チュートリアル:フィルター機能とソート機能を追加する

ここからは少し応用です。実際にアプリを使ってみると「完了したタスクだけ表示したい」「新しい順に並べたい」といった要望が出てきます。ClaudeCodeに改修を依頼してみましょう。

プロンプト例6:「TodoListに『すべて/未完了/完了済み』を切り替えるフィルター機能を追加してください。フィルター状態はApp.tsxで管理し、useTodosからは生のtodosを返すようにしてください。」

App.tsxに次のようなフィルターロジックが追加されます。

import { useState, useMemo } from 'react';

type Filter = 'all' | 'active' | 'completed';

function App() {
  const { todos, addTodo, toggleTodo, deleteTodo } = useTodos();
  const [filter, setFilter] = useState<Filter>('all');

  const visibleTodos = useMemo(() => {
    if (filter === 'active') return todos.filter((t) => !t.completed);
    if (filter === 'completed') return todos.filter((t) => t.completed);
    return todos;
  }, [todos, filter]);

  return (
    <div className="max-w-xl mx-auto p-6">
      <h1 className="text-2xl font-bold mb-4">ToDoアプリ</h1>
      <TodoInput onAdd={addTodo} />
      <div className="flex gap-2 my-4">
        {(['all', 'active', 'completed'] as Filter[]).map((f) => (
          <button
            key={f}
            onClick={() => setFilter(f)}
            className={`px-3 py-1 rounded ${
              filter === f ? 'bg-blue-500 text-white' : 'bg-gray-200'
            }`}
          >
            {f === 'all' ? 'すべて' : f === 'active' ? '未完了' : '完了'}
          </button>
        ))}
      </div>
      <TodoList todos={visibleTodos} onToggle={toggleTodo} onDelete={deleteTodo} />
    </div>
  );
}

useMemoを使うことで、todosやfilterが変わったときだけ絞り込みが再計算されます。パフォーマンス最適化の基本テクニックですが、ClaudeCodeは初心者でも自然に書けるよう導いてくれます。

h2-7. テストコードの自動生成

「動いた!」で終わりにしないのがプロの仕事です。Reactのテストは Vitest と React Testing Library の組み合わせが現代的な定番です。

プロンプト例7:「VitestとReact Testing Libraryを導入し、TodoInputとuseTodosのテストを書いてください。」

セットアップ後、次のようなテストが生成されます。

// src/components/TodoInput.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { describe, it, expect, vi } from 'vitest';
import { TodoInput } from './TodoInput';

describe('TodoInput', () => {
  it('テキストを入力して送信するとonAddが呼ばれる', () => {
    const onAdd = vi.fn();
    render(<TodoInput onAdd={onAdd} />);
    const input = screen.getByPlaceholderText('新しいタスクを入力');
    fireEvent.change(input, { target: { value: '買い物' } });
    fireEvent.click(screen.getByText('追加'));
    expect(onAdd).toHaveBeenCalledWith('買い物');
  });

  it('空文字では送信できない', () => {
    const onAdd = vi.fn();
    render(<TodoInput onAdd={onAdd} />);
    fireEvent.click(screen.getByText('追加'));
    expect(onAdd).not.toHaveBeenCalled();
  });
});

テストを書いておけば、後から機能を追加するときも安心してリファクタリングできます。これがプロダクションコードと趣味コードの最大の違いと言えるでしょう。

h2-8. デプロイ:Cloudflare Pagesへ公開する

完成したアプリは世界中の人に見せたいですよね。社内利用や公開アプリの場合、Cloudflare Pagesが手軽でおすすめです。なお業務用途で認証が必要な場合は、Cloudflare Accessでアクセス制限をかけるのが鉄板の構成です。

ビルドは次のコマンドです。

npm run build

dist/フォルダが生成されます。次にWranglerをインストールしてデプロイします。

npm install -g wrangler
wrangler login
wrangler pages deploy dist --project-name=my-todo-app

数十秒で公開URLが発行されます。Cloudflare Accessでメールアドレス制限をかけたい場合は、Cloudflareダッシュボードから対象アプリにアクセスポリシーを追加するだけで完了です。

プロンプト例(参考):「Cloudflare Pagesにデプロイする手順を、初心者向けにコマンドつきで説明してください。」

ClaudeCodeに聞けば、ログイン手順からトラブルシューティングまで丁寧に教えてくれます。

FAQ

Q1. ClaudeCodeで作ったReactアプリは商用利用できますか? A. はい、生成されたコードは自分のコードとして自由に利用できます。ただし依存ライブラリのライセンス(MITやApache 2.0など)は必ず確認してください。

Q2. JavaScriptとTypeScriptどちらを選ぶべきですか? A. 初学者でもTypeScriptをおすすめします。型があることで、ClaudeCodeとのやり取りも正確になり、エラーを未然に防げます。

Q3. ToDoアプリ以外にはどんな題材がおすすめですか? A. メモアプリ、家計簿、ポモドーロタイマー、簡易ブックマーク管理など、ローカル完結のアプリは練習に最適です。

Q4. 状態管理ライブラリ(Redux, Zustand)は必要ですか? A. ToDoレベルでは不要です。アプリが大きくなり、複数画面でデータを共有するようになったらZustandやJotaiの導入を検討しましょう。

Q5. ClaudeCodeがエラーを直してくれない場合は? A. エラーメッセージをそのまま貼り付けて「このエラーの原因と修正方法を教えて」と尋ねると高確率で解決します。

Q6. デザインセンスがなくても見栄えの良いアプリが作れますか? A. TailwindCSSとshadcn/uiの組み合わせをClaudeCodeに依頼すれば、誰でもモダンなUIに仕上がります。

Q7. 学習を続けるためのおすすめは? A. 公式ドキュメントを横に置きつつ、ClaudeCodeに「このコードを解説して」と聞きながら写経するのが最短ルートです。

まとめ

ClaudeCodeを使えば、Reactアプリの開発は驚くほど身近になります。本記事ではToDoアプリを題材に、環境構築・コンポーネント設計・状態管理・スタイリング・テスト・デプロイまでの一連の流れを体験しました。重要なのは、生成されたコードを「ただ受け取る」のではなく、「なぜこの書き方なのか」を都度ClaudeCodeに尋ねながら理解を深めることです。そうすることで、ツールに頼りつつも自分自身のスキルが確実に積み上がっていきます。次はぜひ、あなたのアイデアを形にしてみてください。

関連記事

[ Advertisement ]

この記事をシェア

Related Articles

あわせて読みたい記事