配列の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 ) );

中でもスプレッドを使っているところに注目してください。配列も中のオブジェクトも、両方とも新しく作り直しています。

使ってよいメソッドの見分け方

迷ったら「元の配列を変えるか、新しい配列を返すか」で判断します。

  • 使える(新しい配列を返す)ものは mapfilterconcatslice、スプレッド
  • 使えない(元を変える)ものは pushpopsplicesortreverse

sortreverse は元を変えるので、並べかえたいときは [...works].sort(...) のようにコピーしてから呼びます。

つまずきどころ

setWorks(works) のように今の配列をそのまま渡しても、入れ物が同じなので画面は変わりません。push したあとにこれを書いて「更新したつもり」になる事故がよくあります。更新関数に渡すのは必ず新しく作った配列です。

演習

作品の追加と削除を、元の配列を変えずに実装します。

ヒント

App.jsx
App.jsx
プレビュー

できているか

  • はじめは「作品 3 件」と表示されている
  • 追加ボタンを押すと作品が 4 件になる
  • 続けて削除ボタンを押すと 写真ギャラリー が消えて 3 件になる