メモウィジェットReact版
ここまでの全部が合流する
メモウィジェットは、JavaScript 入門の総決算として作ったものです。入力して追加し、一覧に並べ、いらなくなったら消します。React で作り直すと、state とリストとフォームという3つの話が1か所で合流します。
命令的に書いていたときは、追加のたびに createElement で li を作り、削除のたびに remove を呼んでいました。React では画面を直接いじりません。データを変えて、画面はデータから描くだけです。
state は2つに分ける
必要な state は次の2つです。
- 入力欄の今の文字(
text) - 追加されたメモの配列(
memos)
この2つを1つにまとめたくなりますが、分けたほうが素直です。入力欄は文字を打つたびに変わり、メモの配列は追加と削除のときだけ変わります。変わるきっかけが違うものは、別の state にします。
const [text, setText] = useState("");
const [memos, setMemos] = useState([]);追加は「新しい配列を作る」
push は使いません。元の配列を書き換えても React は変化に気づかず、画面が更新されないからです。第4章でやったスプレッドで、新しい配列を作って渡します。
function handleSubmit(e) {
e.preventDefault();
const trimmed = text.trim();
if (trimmed === "") return;
setMemos([...memos, { id: Date.now(), text: trimmed }]);
setText("");
}追加のあとに setText("") を呼んでいるのが大事なところです。入力欄の中身も state なので、空文字にすれば画面の入力欄も空になります。自分で input.value = "" と書く必要はありません。
削除は filter
削除は「その id 以外を残した新しい配列」を作ります。
function handleDelete(id) {
setMemos(memos.filter((memo) => memo.id !== id));
}0件のときの画面も用意する
メモが1件も無いときに空の ul だけが残ると、壊れているように見えます。memos.length === 0 で出し分けます。
つまずきどころ
削除ボタンの onClick に onClick={handleDelete(memo.id)} と書くと、描画した瞬間に全部消えます。これは関数を呼んだ結果を渡しているからです。onClick={() => handleDelete(memo.id)} のように、押されたときに動く関数のほうを渡します。
もう1つは key です。メモの文字を key にすると、同じ文字のメモを2つ作ったときに壊れます。追加した時刻から作った id のように、重複しない値を使います。
演習
メモの追加、一覧表示、削除、0件表示までを揃えたメモウィジェットを完成させます。