目次
前回のあらすじ
前回、登録ボタンを押すと、フォームに入力したタイトルと本文がアラートに表示されるようにしました。

今回は、タイトルと本文をTodoコンポーネントの配列に追加して、さらにこの配列でTodoListコンポーネントを更新するところまでを行います。
前回は主にStateを使いましたが、今回はPropsの使い方の話になります。
というわけで、前回のソースコード を元に話を進めます。
準備
TODOリストのデータはTodoコンポーネントのStateで配列として保持することにします。
そのためにまず、1件のTODOデータを扱うオブジェクトのインタフェースTodoDataを定義します。
TodoDataインタフェース
この定義はTodoコンポーネントだけではなくTodoListコンポーネントとTodoItemコンポーネントでも利用するので、Todo.tsxに定義するのではなく別ファイルTodoData.tsxを用意してから、Todo.tsxとTodoList.tsxにインポートして利用します。
TodoData.tsx
|
1 2 3 4 5 6 7 |
export interface TodoData { id: number; title: string; content: string; date: string; time: string; } |
タイトルと本文だけではなく、IDと更新日時もTodoDataで扱うようにします。
Todo.tsx および TodoList.tsx、TodoItem.tsx では、以下の1文を加えてインポートしてください。
|
1 |
import { TodoData } from './TodoData'; |
TodoコンポーネントのPropsとState
次に前回同様、TodoコンポーネントにPropsとStateのインタフェースを定義して、コンストラクタで初期化します。
Todo.tsx
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// Propsインタフェース interface TodoPropsInterface { } // Stateインタフェース interface TodoStateInterface { todoData: TodoData[]; idCount: number; } class Todo extends React.Component<TodoPropsInterface, TodoStateInterface> { public constructor(props:TodoPropsInterface) { super(props); this.state = { todoData: [], idCount: 0, }; } |
StateのメンバtodoDataがTODOデータの格納配列、idCountはIDの配番に使うカウンタです。
クリックリスナの引き上げ
前回、登録ボタンを押すとTodoEditコンポーネントのonClick_Submit()メソッドが呼ばれるようにしました。しかし、このメソッドではTODOデータの格納先であるTodoコンポーネントのStateにアクセスできません。
そこで、onClick_Submit()メソッドをTodoコンポーネントに引き上げます。
ざっくりと処理の流れを説明するとこんな感じです。
TodoコンポーネントにonClick_Submit()メソッドを用意する。TodoコンポーネントからTodoEditコンポーネントのPropsにonClick_Submit()メソッドをわたす。TodoEditコンポーネントは、登録ボタンが押されたら、PropsのonClick_Submit()メソッドを呼ぶ。TodoコンポーネントのonClick_SubmitメソッドでTODOデータを配列に追加する。
この手順に従って実装を進めてみましょう。
onClick_Submit()メソッドを用意する
まず、TodoコンポーネントonClick_Submit()メソッドを用意します。
内容は以下のとおりです。タイトルと本文を受け取って、それを元にTodoDataオブジェクトを作成して配列todoDataに追加する。ついでにidCountを進めています。
Stateを変更する場合は、Stateのメンバ変数を直接変更するのではなくて、必ずsetState()メソッドを使うことに注意してください。
Todo.tsx
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// クリック:登録 private onClick_Submit(title:string, content:string) { if (title == '' || content == '') { alert("タイトルと本文を入力してください。"); return; } // 日時文字列作成 let date = new Date(); let dateStr = date.getFullYear() + "/" + (date.getMonth() + 1) + "/" + date.getDate(); let timeStr = date.getHours() + ":" + date.getMinutes() + ":" + date.getUTCSeconds(); // Todoデータ追加 let todoData = this.state.todoData.slice(); todoData.push({ id: this.state.idCount, title: title, content: content, date: dateStr, time: timeStr, }); this.setState({ todoData: todoData, idCount: this.state.idCount + 1, }); } |
PropsにonClick_Submit()メソッドを加える
TodoEditコンポーネントのPropsにonClick_Submit()メソッドを追加します。
最後のvoidはonClick_Submit()メソッドの戻り値の型です。今回は何も返さないのでvoidです。
TodoEdit.tsx
|
1 2 3 4 |
// Propsインタフェース interface TodoEditPropsInterface { onClick_Submit(title:string, content:string):void; } |
TodoEditコンポーネントのPropsにonClick_Submit()メソッドを追加すると、VisualStudioCodeでは以下のように、render()メソッドでTodoEditコンポーネントがエラーになります。
「TodoEditコンポーネントはPropsにonClick_Submit()メソッドを必要としているのに、それが与えられていない」という警告です。

というわけで与えてやります。
Todo.tsx
|
1 2 3 4 5 6 7 8 9 |
// 描画 public render() { return ( <div> <TodoEdit onClick_Submit={(t, c) => this.onClick_Submit(t, c)}/> <TodoList /> </div> ); } |
PropsのonClick_Submit()メソッドを呼ぶ
TodoEditコンポーネントのonClick_Submit()メソッドは不要になったので削除します。
登録ボタンではPropsのonClick_Submit()メソッドを呼びます。引数のタイトルと本文はTodoEditコンポーネントのStateから渡します。
TodoEdit.tsx
|
1 2 3 4 5 6 7 8 9 10 11 |
// クリック:登録 // private onClick_Submit() { // alert(this.state.title + " " + this.state.content); // } … <div> <button>新規</button> <button onClick={() => this.props.onClick_Submit(this.state.title, this.state.content)} >登録</button> </div> |
TODOデータを配列に追加する
これは前述のonClick_Submit()メソッドのコードの通りです。
TODOリストの表示
配列にTODOデータを追加できるようになりました。ただこれでは内部データに追加されただけなので確認ができません。
そこで次は、TODOデータ配列をTODOリストに表示できるようにします。
ここでもやはりPropsを利用してTodo → TodoList → TodoItemの各コンポーネントへとデータを渡します。
TodoListコンポーネントのProps(とState)
TodoListコンポーネントのPropsにはTodoDataの配列を追加します。
TodoList.tsx
|
1 2 3 4 5 6 7 8 9 10 11 12 |
import {TodoData} from './TodoData'; // Propsインタフェース interface TodoListPropsInterface { todoData:TodoData[]; } // Stateインタフェース interface TodoListStateInterface { } class TodoList extends React.Component<TodoListPropsInterface, TodoListStateInterface> { |
TodoItemコンポーネントのProps(とState)
TodoItemコンポーネントは1件のTODOデータを扱うだけなので、PropsにはTodoDataをひとつ追加します。
TodoItem.tsx
|
1 2 3 4 5 6 7 8 9 10 11 12 |
import {TodoData} from './TodoData'; // Propsインタフェース interface TodoItemPropsInterface { todoData: TodoData; } // Stateインタフェース interface TodoItemStateInterface { } class TodoItem extends React.Component<TodoItemPropsInterface, TodoItemStateInterface> { |
TODOデータの表示
あとは上から順にデータを渡して、TodoItemコンポーネントで表示するだけです。
まずTodoコンポーネントからTodoListコンポーネントへTODOデータ配列を渡します。
Todo.tsx
|
1 2 3 4 5 6 7 8 9 |
// 描画 public render() { return ( <div> <TodoEdit onClick_Submit={(t, c) => this.onClick_Submit(t, c)}/> <TodoList todoData={this.state.todoData} /> </div> ); } |
次に、TodoListコンポーネントからTodoItemコンポーネントへTODOデータをひとつずつ渡します。
JSX内でループすることができないので、まずitemsを組み立ててからJSXに組み込んでいる点に注目してください。
TodoList.tsx
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// 描画 render() { const items = this.props.todoData.map((d) => { return <TodoItem todoData={d} />; }); return ( <div> <table className='todo-table'> <tr> <th>タイトル</th> <th>本文</th> <th>日付</th> <th>時刻</th> <th></th> <th></th> </tr> {items} </table> </div> ) } |
最後にTodoItemコンポーネントでの表示部分の修正です。
TodoItem.tsx
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// 描画 render() { return ( <tr> <td>{this.props.todoData.title}</td> <td>{this.props.todoData.content}</td> <td>{this.props.todoData.date}</td> <td>{this.props.todoData.time}</td> <td><button>編集</button></td> <td><button>削除</button></td> </tr> ); } |
次回に続く
今回はここまでです。
TODOリストに行を追加できるようになりました。

ここまでの ソースコード です。
次回は編集ボタンと新規ボタンの動作を実装して、この一連の記事を締め括りたいと思います。
