実践練習: ToDo アプリ
ToDo アプリの機能
- ToDo アイテムの追加
- ToDo アイテムの一覧表示
- 各 ToDo アイテムの完了/未完了の切り替え
- 完了した ToDo アイテムの削除
ToDo アプリの構成
- ToDo リストコンポーネント (
TodoList.js
): ToDo アイテムの一覧を表示し、各アイテムの状態を切り替える機能を提供します。 - ToDo アイテム追加コンポーネント (
AddTodoItem.js
): 新しい ToDo アイテムを追加するフォームを提供します。 - ToDo アイテムコンポーネント (
TodoItem.js
): 個々の ToDo アイテムを表示し、完了/未完了の状態を切り替えるチェックボックスを提供します。
ステップバイステップの実装
- プロジェクトのセットアップ:
SolidJS プロジェクトを初期化し、必要な依存関係をインストールします。 - ToDo リストコンポーネントの実装:
ToDo リストの状態を管理し、ToDo アイテムの一覧を表示します。また、アイテムの追加と削除のロジックを含みます。import { createSignal, For } from 'solid-js'; function TodoList() { const [todos, setTodos] = createSignal([]); return ( <div> <h2>ToDo List</h2> <ul> <For each={todos()}> {(todo) => ( <li> {todo.title} - {todo.completed ? 'Completed' : 'Incomplete'} </li> )} </For> </ul> </div> ); } export default TodoList;
- ToDo アイテム追加コンポーネントの実装:
ユーザーが新しい ToDo アイテムを入力し、リストに追加できるフォームを提供します。フォームの送信時には、リストの状態が更新されます。import { createSignal } from 'solid-js'; function AddTodoItem(props) { const [newTodo, setNewTodo] = createSignal(''); const submitHandler = (e) => { e.preventDefault(); if (newTodo().trim()) { props.onAddTodo({ title: newTodo(), completed: false }); setNewTodo(''); } }; return ( <form onSubmit={submitHandler}> <input type='text' value={newTodo()} onInput={(e) => setNewTodo(e.target.value)} placeholder='Add new todo' /> <button type='submit'>Add</button> </form> ); } export default AddTodoItem;
このコンポーネントでは、onAddTodo
という props を通じて、親コンポーネントから ToDo アイテム追加の関数を受け取ります。ユーザーがフォームを送信すると、この関数が新しい ToDo アイテムオブジェクトを引数にして呼び出されます。 - ToDo アイテムコンポーネントの実装:
各 ToDo アイテムを表示し、完了/未完了の状態を切り替える機能を提供します。アイテムが完了とマークされた場合、ビジュアル的に区別がつくようにします。
このコンポーネントでは、onToggle
とonDelete
という props を通じて、親コンポーネントから ToDo アイテムの完了/未完了の切り替えと削除の関数を受け取ります。チェックボックスの状態が変更されると、onToggle
関数が呼び出され、Delete
ボタンがクリックされると、onDelete
関数が呼び出されます。function TodoItem(props) { const toggleCompleted = () => { props.onToggle(props.id); }; const deleteTodo = () => { props.onDelete(props.id); }; return ( <li> <input type='checkbox' checked={props.completed} onChange={toggleCompleted} /> <span style={{ textDecoration: props.completed ? 'line-through' : 'none' }} > {props.title} </span> <button onClick={deleteTodo}>Delete</button> </li> ); } export default TodoItem;
- 外部 API との連携準備:
例として、簡単な ToDo リストアイテムを返す外部 API が存在すると仮定します。この API から ToDo リストアイテムの一覧を取得し、アプリケーションに表示します。 - ToDo リストコンポーネントに API からデータを取得する処理の追加:
src/components/TodoList.js
に、API からデータを取得し表示するコンポーネントを作成します。 このコンポーネントでは、createEffect
を使用してコンポーネントのマウント時にfetchTodos
関数を実行し、API から ToDo リストアイテムのデータを非同期に取得します。取得したデータはtodos
シグナルに保存され、For
ディレクティブを使用してリストアイテムとして表示されます。import { createEffect, createSignal, For } from 'solid-js'; function TodoList() { const [todos, setTodos] = createSignal([]); const fetchTodos = async () => { try { const response = await fetch('https://example.com/api/todos'); if (!response.ok) { throw new Error('Failed to fetch todos'); } const data = await response.json(); setTodos(data); } catch (error) { console.error('Fetch error:', error); // ここでエラーメッセージを表示するなどの処理を行う } }; createEffect(() => { fetchTodos(); }); return ( <div> <h2>ToDo List</h2> <ul> <For each={todos()}> {(todo) => ( <li> {todo.title} - {todo.completed ? 'Completed' : 'Incomplete'} </li> )} </For> </ul> </div> ); } export default TodoList;