😀

ReactでDOMもデータも更新されているのにブラウザの表示が変わらない時に確認すること

2017/07/27に公開1

Reactでデータは更新されているのに、ブラウザ上の表示が変わらないってことないですか?

しっかりReactを使えている人にとっては起こらない現象かもしれませんが、ちゃんと理解せず使っているとハマってしまうかもしれません。

データも開発者ツールもDOMが更新されている

consoleでデータを確認しても、要素を調査でDOMを確認しても意図した通りになっています。

だけどブラウザ上では変化が起きない。

そんな馬鹿な…と思うかもしれませんが、Reacrだとありえるんですよね。

keyをチェックする

Reactではループをする要素には個別のkeyを設定する必要があります。

keyが正しく設定できていない場合にはブラウザ上での表示が更新されないという状態になります。

例えば下記のような場合。

const items = [
  { id: 1, name: 'item1' },
  { id: 2, name: 'item2' },
  { id: 3, name: 'item3' },
]
items.map((item, i) => {
  return (<div key={i}>{item.name}</div>);
});

idが2のデータを削除するとブラウザ上ではidが1と2のデータが残り3のデータが消えてしまいます。

consoleでデータを確認しても1と3のデータが残っていて矛盾が起きます。

keyは必ずデータに紐付いた一意の値を指定する

ブラウザ上で表示がおかしくなる原因はkeyにデータに紐づく一意の値が設定されていないからです。

上記のループのインデックスでkeyを設定している場合、データを3つの状態から1つ削除するとインデックスは0と1になります。

そのため元々keyが0と1の要素が表示された状態となり変化が起きないということになってしまいます。
正しく動作させるコードは下記。

const items = [
  { id: 1, name: 'item1' },
  { id: 2, name: 'item2' },
  { id: 3, name: 'item3' },
]
items.map((item, i) => {
  return (<div key={item.id}>{item.name}</div>);
});

keyはどんな場合においても一意な値で開発を進める

実際はデータに紐づくidのような固有の値があることがほとんどですが、開発中だとidがない場合も想定されます。

とりあえずループのインデックスを指定して開発を進めるというパターンだと今回紹介したような状況に陥ってしまうことが考えられますね。

後からデバッグすると気づかないことも多く、開発中と言っても、keyを指定する場合は必ず一意の値を指定するようにしましょう。

Discussion

XU ZHONGWEIXU ZHONGWEI

data2が削除され、dataの1と3が残りますが、keyがないから、差分検出処理の時に、reactが認識できるのは2番名のdomを削除するではなく、domを一つ減らすことだけです。
結局3番目のdom要素をdomから削除することになりました