配列のstate
配列も同じ考え方
作品の一覧のように、増えたり減ったりするデータは配列の state にします。
const [works, setWorks] = useState([
{ id: 1, title: "レシピ検索アプリ", category: "web" },
{ id: 2, title: "買い物メモツール", category: "tool" },
{ id: 3, title: "写真ギャラリー", category: "web" },
]);オブジェクトのときと同じルールが効きます。元の配列を書きかえず、新しい配列を作って渡す のが React のやり方です。
追加する
配列に足す方法としてまず思いつくのは push です。しかし push は元の配列そのものを変えるので、React から見ると入れ物が同じままです。画面は変わりません。
// 動かない
works.push({ id: 4, title: "ポートフォリオサイト" });正しくはスプレッドで新しい配列を作ります。
setWorks([...works, { id: 4, title: "ポートフォリオサイト", category: "web" }]);...works が今の要素をすべて展開し、そのうしろに新しい 1 件を並べています。先頭に足したいときは順番を入れかえて [新しい要素, ...works] と書きます。
削除する
削除には filter を使います。filter は条件に合う要素だけを集めた 新しい配列 を返すので、そのまま更新関数に渡せます。
setWorks(works.filter((work) => work.id !== 3));「id が 3 でないものだけ残す」という書き方です。splice は元の配列を変えてしまうので使いません。
書きかえる
1 件だけ内容を変えたいときは map です。条件に合う要素だけ新しいオブジェクトに差しかえ、それ以外はそのまま返します。
setWorks(
works.map((work) =>
work.id === 2 ? { ...work, title: "買い物メモ v2" } : work
)
);中でもスプレッドを使っているところに注目してください。配列も中のオブジェクトも、両方とも新しく作り直しています。
使ってよいメソッドの見分け方
迷ったら「元の配列を変えるか、新しい配列を返すか」で判断します。
- 使える(新しい配列を返す)ものは
map、filter、concat、slice、スプレッド - 使えない(元を変える)ものは
push、pop、splice、sort、reverse
sort と reverse は元を変えるので、並べかえたいときは [...works].sort(...) のようにコピーしてから呼びます。
つまずきどころ
setWorks(works) のように今の配列をそのまま渡しても、入れ物が同じなので画面は変わりません。push したあとにこれを書いて「更新したつもり」になる事故がよくあります。更新関数に渡すのは必ず新しく作った配列です。
演習
作品の追加と削除を、元の配列を変えずに実装します。