React · LEARN AT YOUR OWN PACE今日も、一歩ずつ。

LESSON 05 · 約35分

配列を表示し、不変に更新する

map・key・filterを使い、項目の同一性を保ちながら一覧を変更します。

コードを試す前に

01のVite reactテンプレート(JavaScript/JSX)を使います。特記のないApp.jsxは、そのレッスンだけで動く独立した例です。例同士を連結しないでください。

短い学習用の例です。各App.jsxは独立した例で、順に追記して一つの完成品にする形式ではありません。ファイル名、依存関係、未定義部分の前提は注記に記載します。問題内の抜粋や空欄は、そのまま実行するための完成コードではありません。

開発環境の準備を確認する →

このレッスンでわかること

  • 安定したIDをkeyにできる
  • 元の配列やオブジェクトを変えずに項目を更新できる

mapで部品の配列を作る

items.mapは項目ごとにJSXを返します。直接返す最上位の要素にkeyを指定します。keyは、追加・削除・並び替え後も同じ項目を見分ける手がかりです。データが持つ安定したidを使い、描画するたびに乱数を作りません。順序が変わる一覧では配列の添字も避けます。

stateは置き換える

追加なら[...items, newItem]、削除ならfilter、特定項目の変更ならmapを使います。配列をコピーしただけでは中のオブジェクトは同じ参照です。変える項目も{ ...item, done: !item.done }のように新しく作り、他の項目はそのまま返します。

識別子と表示を分ける

タイトルは重複したり編集されたりします。idを別に持つと、どの行を操作するかが明確です。key自体は子コンポーネントへ通常のpropsとして渡されません。子でもIDを使うならid={item.id}を別に渡します。完了件数はitemsから計算すれば、別stateとの同期が不要です。

完了チェックと削除

src/App.jsx
import { useState } from 'react';

const initialItems = [
  { id: 1, title: 'JSXを読む', done: false },
  { id: 2, title: 'propsを渡す', done: true },
];

export default function App() {
  const [items, setItems] = useState(initialItems);

  function toggle(id) {
    setItems(current => current.map(item =>
      item.id === id ? { ...item, done: !item.done } : item
    ));
  }

  return (
    <main>
      <h1>チェックリスト</h1>
      <p>{items.filter(item => item.done).length}件完了</p>
      <ul>
        {items.map(item => (
          <li key={item.id}>
            <label>
              <input type="checkbox" checked={item.done} onChange={() => toggle(item.id)} />
              {item.title}
            </label>
            <button type="button" onClick={() =>
              setItems(current => current.filter(row => row.id !== item.id))
            }>{item.title}を削除</button>
          </li>
        ))}
      </ul>
      {items.length === 0 && <p>項目はありません。</p>}
    </main>
  );
}

checkboxはcheckedで真偽値を渡します。具体的な入力の扱いは次のレッスンで確かめます。

TRY IT YOURSELF

一覧の項目を操作する

  1. 先頭の項目を完了にし、件数が増えることを確認する
  2. 先頭を削除し、残った行の内容とチェック状態が保たれることを確認する
  3. 全件削除して0件の表示を確認する
  4. setItems(current => [...current].reverse())を使う並び替えボタンを追加する

できたらOK:チェック・削除・並び替え後も、操作したIDと表示の状態が一致する

QUICK CHECK

理解を確かめよう

削除や並び替えをする一覧のkeyに、最も適切なのはどれ?

公式資料でもう少し詳しく

ここまで読めたら、ひとつ前進。