0Pricing
React Academy · レッスン

KeyとRefのベストプラクティス

安定したkeyを使い、indexをkeyにする際の問題を避け、コールバックrefを扱います

「KeyとRefのベストプラクティス」はCoddyKit上の無料React Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはReact Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 React Academyコースには全4レッスンが含まれています。

ようこそ

このレッスンでは、リストの key を正しく使用する方法、配列のインデックスを key にするとバグが発生する理由、コールバック ref と転送 ref の扱い方を学びます。

Key が重要な理由

React は `key` props を使って、レンダリング間でリスト内のどの項目が変更、追加、削除されたかを追跡します。正しい key があれば既存の DOM ノードを再利用できますが、誤った key を使うと不要なアンマウントと再マウントが発生します。

安定した一意の Key

最適な key は、データに含まれる安定した一意の ID です。たとえば、データベースの行 ID や UUID を使用します。この key はページ全体で一意である必要はなく、兄弟要素の中でのみ一意であれば十分です。
users.map(user => (
  <UserCard key={user.id} user={user} />
))

インデックスを Key にする問題点

配列のインデックスを key にする方法は静的なリストでは問題ありませんが、並べ替えやフィルタリングを行うリストではバグの原因になります。項目の順序が変わると、React はインデックスでコンポーネントを対応付け、誤った DOM ノードを再利用するため、入力値やアニメーションの state が壊れます。
// Risky when list can reorder or filter
items.map((item, i) => <Row key={i} {...item} />)

インデックス Key を使用できる場合

インデックスを key にしてよいのは、次の条件をすべて満たす場合だけです。(1) リストの並べ替えやフィルタリングを行わない、(2) 項目に安定した ID がない、(3) 項目がローカル state(入力値など)を持たない。静的な表示用リストであれば問題ありません。

安定した ID の生成

データに ID がない場合は、レンダリング中ではなく、項目を作成するときに ID を生成してください。`crypto.randomUUID()` または `nanoid` ライブラリを使用できます。
const newItem = { id: crypto.randomUUID(), text: 'Buy milk' };

useRef の基本

`useRef` は、再レンダリングを発生させずにレンダリング間で `.current` の値を保持する、変更可能なオブジェクトを返します。DOM への参照やタイマー ID などの変更可能な値を保持するために使用します。
const inputRef = useRef(null);
<input ref={inputRef} />
// Access DOM node: inputRef.current.focus();

コールバック Ref

ref オブジェクトを渡す代わりに、**コールバック ref** を渡すことができます。これは、マウント時に DOM ノードを受け取り、アンマウント時に `null` を受け取る関数です。ノードが利用可能になったタイミングで、正確に処理を設定できます。
function Input() {
  return (
    <input
      ref={node => {
        if (node) node.focus();
      }}
    />
  );
}

コンポーネントの Ref に使う forwardRef

関数コンポーネントは通常の prop として `ref` を受け取りません。コンポーネントを `React.forwardRef` でラップすると、親コンポーネントから内部の DOM ノードに ref をアタッチできるようになります。
const FancyInput = React.forwardRef((props, ref) => (
  <input ref={ref} className="fancy" {...props} />
));

// Parent
const inputRef = useRef(null);
<FancyInput ref={inputRef} />

useImperativeHandle

親コンポーネントが子コンポーネントへの ref を保持している場合、`useImperativeHandle` を使って子が公開する内容を正確に制御できます。これにより、子の内部 DOM を非公開にしたまま、明確な命令型 API を提供できます。
const Child = forwardRef((_, ref) => {
  const innerRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => innerRef.current.focus(),
  }));
  return <input ref={innerRef} />;
});

確認問題

並べ替えが可能なリストで、配列のインデックスを key として使用するのを避けるべきなのはなぜですか?

まとめ

データの安定した ID を key として使用し、動的なリストではインデックスを key にすることを避けてください。DOM へのアクセスや変更可能な値には useRef を使用し、マウントやアンマウント時の処理にはコールバック ref を使用します。また、子コンポーネントから ref を公開するには forwardRef を使用します。

次のレッスン

次のレッスンは **Folder Structure & Naming Conventions** です。機能ベースのフォルダーと一貫したファイル命名を使って、React プロジェクトを整理する方法を学びます。

よくある質問

「KeyとRefのベストプラクティス」レッスンは無料ですか?

はい。「KeyとRefのベストプラクティス」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、React Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 React Academyコースには全4レッスンが含まれています。

「KeyとRefのベストプラクティス」で何を学びますか?

安定したkeyを使い、indexをkeyにする際の問題を避け、コールバックrefを扱います ブラウザで直接実行するハンズオンコードでReact Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

React Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのReact Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「KeyとRefのベストプラクティス」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このReact Academyレッスンでコードを書いて実行できますか?

はい。すべてのReact Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. StrictModeの動作
  2. Pure Componentsとrenderでの副作用回避
  3. KeyとRefのベストプラクティス
  4. フォルダー構成と命名規則
← React Academyに戻る