このチュートリアルでは、Vite、TypeScript、そしてTailwind CSSを使用してシンプルなタスク管理アプリを作成する方法を解説します。
こんな感じの「タスク管理アプリ」を10分ぐらいで作れます。
React と TypeScript の基礎を丁寧に解説していますので、初心者の方でも安心して取り組むことができるかと思います!
では、早速始めていきましょう!
1. プロジェクトの作成
まず、新しいReactプロジェクトを作成します。
ターミナル(or コマンドプロンプト、PowerShell)を開き、以下のコマンドを実行します。
npm create vite@latest task-management-app -- --template react-ts
このコマンドは以下のことを行っています。
- Viteを使用してReact + TypeScriptのプロジェクトを作成
- プロジェクト名を「task-management-app」に設定
終わりましたら、以下のようなディレクトリ構造が作成されます。
では、作成したプロジェクトディレクトリに移動します。
cd task-management-app
今回はビルドツールとして「Vite」を使用しています。
Viteは高速な開発環境とビルドツールを提供するモダンなフロントエンド開発環境です。
2. 依存関係のインストール
プロジェクトディレクトリ内で以下のコマンドを実行します。
npm install
npm install
は、プロジェクトの基本的な依存関係をインストールします。
次に、Tailwind CSSをプロジェクトに追加します。
以下のコマンドを実行してください。
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
このコマンドで、Tailwind CSSとその関連パッケージをインストールできます。
各パッケージの説明
- tailwindcss: スタイリングのためのユーティリティファーストCSSフレームワーク
- postcss: CSSを変換するためのツール
- autoprefixer: ベンダープレフィックスを自動的に追加するPostCSSプラグイン
では次に、Tailwind CSSを設定していきます。
3. Tailwind CSSの設定
Tailwind CSSを使用するための設定ファイルを生成します。
以下のコマンドを実行してください。
npx tailwindcss init -p
このコマンドで、tailwind.config.js
とpostcss.config.js
の2つの設定ファイルを生成します。
次に、tailwind.config.js
ファイルを以下のように編集します。
module.exports = {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
上記の content
で、 Tailwind CSSのユーティリティクラスを使用するファイルのパターンを指定しています。
ここでは、index.html
とsrc
ディレクトリ内のJavaScript/TypeScriptファイルを対象にしています。
これでTailwind CSSの基本的な設定が完了しました。
ただ、これだけではTailwind CSSのスタイルが適用されないため、プロジェクトのCSSファイルを編集する必要があります。
4. CSSファイルの作成
src/index.css
ファイルを以下の内容で置き換えます。
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
Tailwind CSSの基本スタイル、コンポーネントスタイル、ユーティリティクラスをプロジェクトにインポートしていますので、Tailwind CSSのすべての機能を使用できるようになります。
5. 型定義の作成
TypeScriptを使用する利点の1つは、型定義によってコードの安全性を高められることです。
では早速、タスク管理アプリで使用する「タスク」の型を定義しましょう。
今回はタスク一つひとつが持つIDとテキストの2つのプロパティを持つオブジェクトを定義します。
src/types.ts
ファイルを作成し、以下の内容を記述します。
export interface Task {
id: number;
text: string;
}
Task 型定義の説明
-
Task
は、id
とtext
の2つのプロパティを持つオブジェクトを表します。 -
id
は数値型(number)で、各タスクを一意に識別するために使用されます。 -
text
は文字列型(string)で、タスクの内容を表します。
型定義を使用することで、コード内でタスクを扱う際に、IDやテキストが適切な型であることを保証し、潜在的なバグを防ぐことができます。
例えば、間違った型の値を代入しようとすると、TypeScriptがエラーを検出してくれます。
(例:id: '123'
など)
6. コンポーネントの作成
Reactでは、UIを再利用可能な部品(コンポーネント)に分割することで、効率的な開発が可能になります。
今回のアプリでは、タスクの入力フォームとタスクリストの2つの主要なコンポーネントを作成します。
まず、src/components
ディレクトリを作成してください。このディレクトリ内に、以下の2つのファイルを作成します。
-
TaskForm.tsx
: 新しいタスクを追加するためのフォームを表すコンポーネント -
TaskList.tsx
: タスクのリストを表示するコンポーネント
ファイルが作れたら、それぞれのコンポーネントの中身を作成していきます。
TaskForm.tsx
これは新しいタスクを追加するためのフォームを表すコンポーネントです。
中身を以下のように記述してください。
import React, { useState, useCallback } from 'react';
interface TaskFormProps {
addTask: (text: string) => void;
}
const TaskForm: React.FC<TaskFormProps> = ({ addTask }) => {
const [task, setTask] = useState('');
const handleSubmit = useCallback((e: React.FormEvent) => {
e.preventDefault();
if (task.trim()) {
addTask(task);
setTask('');
}
}, [task, addTask]);
return (
<form onSubmit={handleSubmit} className="flex gap-2 mb-4">
<input
type="text"
value={task}
onChange={(e) => setTask(e.target.value)}
placeholder="新しいタスクを入力"
className="flex-grow px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<button
type="submit"
className="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500"
>
追加
</button>
</form>
);
};
export default TaskForm;
このコンポーネントで使っている React の機能や、JavaScript のコードのポイントを簡単に説明しておきます。
以下、TaskFormコンポーネントの解説
-
useState
フック:-
task
という状態変数を作成し、入力フィールドの現在の値を保持します。 -
setTask
関数を使って、ユーザーの入力に応じてtask
の値を更新します。
-
-
useCallback
フック:-
handleSubmit
関数をメモ化(最適化)します。 - フォームが送信されたときに呼び出され、新しいタスクを追加します。
-
-
Tailwind CSS クラス:
-
className
属性に直接スタイルを適用しています。 - 例えば、
flex gap-2 mb-4
はフレックスボックスレイアウト、要素間の間隔、下部のマージンを設定します。
-
-
フォームの挙動:
-
preventDefault()
を使用して、フォーム送信時のページリロードを防いでいます。 - 入力が空でない場合のみ、新しいタスクを追加します。
-
-
アクセシビリティ:
-
focus
状態のスタイリングにより、キーボード操作性を向上させています。
-
次に、タスクリストを表示するコンポーネントを作成します。
TaskList.tsx
これはタスクのリストを表示するコンポーネントです。
中身を以下のように記述してください。
import React from 'react';
import { Task } from '../types';
interface TaskListProps {
tasks: Task[];
removeTask: (id: number) => void;
}
const TaskList: React.FC<TaskListProps> = ({ tasks, removeTask }) => {
return (
<ul className="space-y-2">
{tasks.map((task) => (
<li key={task.id} className="flex items-center justify-between p-2 bg-gray-100 rounded-md">
<span>{task.text}</span>
<button
onClick={() => removeTask(task.id)}
className="px-2 py-1 bg-red-500 text-white rounded-md hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500"
>
削除
</button>
</li>
))}
</ul>
);
};
export default TaskList;
以下、TaskListコンポーネントの解説
-
Props型定義:
-
TaskListProps
インターフェースで、このコンポーネントが受け取るプロパティの型を定義しています。 -
tasks
はTask
オブジェクトの配列で、表示するタスクのリストです。 -
removeTask
は関数で、タスクを削除するために使用されます。
-
-
タスクのマッピング:
-
tasks.map()
を使用して、各タスクをリストアイテムにレンダリングしています。
-
-
キーの使用:
- 各リストアイテムに
key
プロパティを設定しています - これがないと、Reactがリストの変更を追跡できなくなりますので、忘れずに設定してください。
- 各リストアイテムに
-
イベントハンドリング:
- 削除ボタンに
onClick
イベントを設定し、対応するタスクを削除できるようにしています。
- 削除ボタンに
-
Tailwind CSSクラス:
- リストアイテムのレイアウトやスタイリングに Tailwind CSS のユーティリティクラスを使用しています。
これらのコンポーネントにより、タスクの追加と削除を行うためのUIが作成されました。
次は、これらのコンポーネントを組み合わせて、アプリケーション全体を構築していきます。
7. App.tsxの更新
最後に、アプリケーションのメインコンポーネントである App.tsx
を更新します。
このファイルでは、先ほど作成した TaskForm
と TaskList
コンポーネントを統合し、アプリケーション全体の状態を管理します。
src/App.tsx
ファイルを以下の内容で置き換えてください。
import React, { useState, useCallback } from 'react';
import TaskForm from './components/TaskForm';
import TaskList from './components/TaskList';
import { Task } from './types';
const App: React.FC = () => {
const [tasks, setTasks] = useState<Task[]>([]);
const addTask = useCallback((newTask: string) => {
setTasks((prevTasks) => [...prevTasks, { id: Date.now(), text: newTask }]);
}, []);
const removeTask = useCallback((id: number) => {
setTasks((prevTasks) => prevTasks.filter((task) => task.id !== id));
}, []);
return (
<div className="container mx-auto p-4 max-w-md">
<div className="bg-white shadow-md rounded-lg p-6">
<h1 className="text-2xl font-bold text-center mb-4">タスク管理アプリ</h1>
<TaskForm addTask={addTask} />
<TaskList tasks={tasks} removeTask={removeTask} />
</div>
</div>
);
};
export default App;
以下、Appコンポーネントの解説
-
状態管理:
-
useState
フックを使用してtasks
状態を管理しています。 - これは
Task
オブジェクトの配列です。
-
-
タスク追加機能:
-
addTask
関数はuseCallback
でメモ化されています。 - 新しいタスクを作成し、既存のタスクリストに追加します。
-
Date.now()
を使用して一意のIDを生成しています。
-
-
タスク削除機能:
-
removeTask
関数もuseCallback
でメモ化されています。 - 指定されたIDのタスクをリストから削除します。
-
-
コンポーネントの組み合わせ:
-
TaskForm
とTaskList
コンポーネントを使用して、UIを構築しています。 - 必要な props(
addTask
、tasks
、removeTask
)を各コンポーネントに渡しています。
-
この App
コンポーネントは、アプリケーション全体の構造と状態管理を担当します。
タスクの追加と削除のロジックをここで定義し、それらの機能を子コンポーネントに渡すことで、整理された構造を維持しています。
今回のアプリに限らず、Reactアプリケーションでは、親コンポーネントが状態を管理し、子コンポーネントに渡すというパターンが一般的です。
8. アプリケーションの実行
これで、タスク管理アプリの開発が完了しました!
では、アプリケーションを起動して動作を確認しましょう。以下のコマンドを実行してください。
npm run dev
このコマンドは開発サーバーを起動します。
コマンドが成功すると、ターミナルに表示されるURLをブラウザで開くことができます(通常は http://localhost:5173
です)。
ブラウザでアプリケーションが表示されたら、以下の操作を試してみてください。
- 入力フォームにタスクを入力し、「追加」ボタンをクリックします。
- 新しいタスクがリストに追加されることを確認します。
- タスクの横にある「削除」ボタンをクリックして、タスクを削除できることを確認します。
実際に動かしてみると、以下のようになります。
入力フォームにテキストを入力して「追加」ボタンをクリックすると、タスクが追加されます。
もちろん、削除ボタンをクリックするとタスクが削除されます。
これで、Reactを使用した基本的なタスク管理アプリケーションが完成しました!
まとめ
いかがでしたでしょうか?
このチュートリアルを通じて、以下の重要な概念とツールについて学ぶことができました。
- Vite: 高速な開発環境とビルドツールを提供するモダンなフロントエンド開発環境
- TypeScript: JavaScriptに型システムを追加し、コードの品質と保守性を向上させる言語
- Tailwind CSS: 効率的なスタイリングを可能にするユーティリティファーストのCSSフレームワーク
- Reactコンポーネント: UIを再利用可能な部品に分割する概念
- Reactフック(useState, useCallback): 関数コンポーネントで状態や副作用を管理するための機能
このアプリケーションをベースに、さらに機能を追加したり、デザインをカスタマイズしたりして、自分だけのオリジナルアプリを作ってみると面白いかもしれませんね。
例えば、以下のような機能を追加してみるのも良いでしょう。
- タスクの完了状態を管理する(チェックボックスの追加)
- タスクの編集機能
- タスクの優先度や期限の設定
- ローカルストレージを使用したタスクの永続化
ちょっと宣伝:もっとReactを学びたい方へ
個人的に技術ブログも書いており、Reactに関する記事も多数公開しています。
興味があれば、以下の記事もチェックしていただけると大変励みになります...!