React が「なぜ再レンダリングするのか?」実際に動かして確認したことのメモ

React が「なぜ再レンダリングするのか?」実際に動かして確認していった記録

React を触り始めた頃、「なぜここで再レンダリングが起きるのだろう?」と戸惑う場面がいくつかありました。

ドキュメントには「state が更新されると再レンダリングされます」と書かれているものの、実際に書いて動かしてみると、
「値は変わっていないはずなのに再レンダリングされている?」という状況が起き、仕組みを正しく理解できていないことに気づきました。

そこで、気になった挙動をひとつずつ調べたり、手元で試しながら整理した内容をまとめています。

■ 1. setState を呼ぶと、値が同じでも再レンダリングされる

まず最初に違和感を覚えたのがこれでした。


setCount(0);

count がすでに 0 でも、このコードを実行するとコンポーネントは再レンダリングされます。

なぜなのか気になって調べてみると、React は「値が変わったか」を見ているのではなく、
「state の更新が依頼されたかどうか」 を基準に判断しているということが分かりました。

つまり、値が同じでも「更新が行われた」という事実だけで再レンダリングが発生します。

■ 2. 配列やオブジェクトが“同じ内容でも毎回別物扱い”される理由

次に気になったのが、こちらの挙動です。


setUser({ name: "Taro" });

「中身は同じなのに、なぜ再レンダリングされるのか?」という疑問がありました。

実際に比較して確認してみると、次の結果になります。


{} === {} // false

オブジェクトは “参照型” のため、見た目が同じでも毎回新しく作られ、メモリ上では別々の参照になります。
React もこの「参照の違い」を根拠に更新を判断するため、同じ内容を渡しても「更新された」と解釈します。

【Tips】なぜ {} === {} は false になるのか?

  • オブジェクトは“実体”ではなく「参照」で比較される
  • {} を書くたびに新しいオブジェクトが生成される
  • そのため {} === {} は一致しない(false)

React はオブジェクトの中身までは比較せず、参照が変わったかどうか を基準にするため、再レンダリングの理由になります。

■ 3. useRef の値は変わっても再レンダリングされない

state と useRef の違いも実際に試してみると理解が進みました。


const countRef = useRef(0);

function increment() {
  countRef.current++;
  console.log(countRef.current);
}

このコードでは値は増えますが、画面の表示はまったく変わりません。
「useRef は値が変わっても再レンダリングを引き起こさない」というのを実際に確認した瞬間です。

ここで、画面に出さない値は state にしなくてよい という考え方が自然と腑に落ちました。

■ 4. 関数が毎レンダーで生成されることが子コンポーネント再レンダリングの原因だった

子コンポーネントが意図せず再レンダリングされる理由が分からず、props に渡している関数にログを仕込んで調べてみました。


<Child onClick={() => doSomething()} />

調べてみると、無名関数はレンダーのたびに新しい関数として生成されるため、
React は「props が変わった」と解釈し、子コンポーネントを再レンダリングしていました。

この挙動を理解したことで、useCallback を使う意味が明確になりました。

■ 5. setState の直後に値を読むと“古い値”になる理由

次に、setState の直後に console.log を置いてみたところ、意図した値が出ないことに気づきました。


setCount(count + 1);
console.log(count); // 更新されていない

調べてみると、React の state 更新は同期的ではなく、次のレンダリングで反映される という仕組みのためでした。

そこで、関数型アップデートを使うと常に最新の値を扱えることが分かりました。


setCount(prev => prev + 1);

■ 6. 親が再レンダリングすると子も再レンダリングされる

props が変わっていないのに子コンポーネントがレンダリングされる場面があり、気になって調べてみると、React は基本的に、
親が再レンダリングされると子も再レンダリングされる という仕様で動いていることが分かりました。

ここを理解してから、必要な場合に React.memo を使う意味がよりはっきりしました。

■ まとめ:実際に動かしていくと理解が進む

React の再レンダリングは仕組みだけ見ると複雑そうに見えますが、実際にログを出したり小さなコードを書いて確かめていくと、動き方が自然に掴めてきました。

  • setState が呼ばれると値が同じでも再レンダリング
  • 参照型(オブジェクト / 配列)は毎回別物として扱われる
  • 表示に関係ない値は useRef に置くほうが適切
  • 関数は毎回生成されるため props 経由で再レンダリングが増える
  • state は「次のレンダー」で反映される仕組み

こうした挙動をひとつずつ確認していくことで、React の再レンダリングの仕組みがより理解しやすくなりました。

コメント

タイトルとURLをコピーしました