何が再レンダリングを起こすか

Part 7 · レンダリングの仕組み

何が再レンダリングを起こすか

props が変わったから、ではない

再レンダリングが起きる理由は 2 つだけです。 自分の state が変わったときと、親がもう一度描き直されたときです。

ここで大切なのは、props が変わったからではないということです。 親が再レンダリングされると、子も再レンダリングされます。

子が props を受け取っていなくても再レンダリングされる

下のデモでは、子コンポーネントに props を渡していません。 それでも親のボタンを押すと、子の render 回数が増えます。

親の更新で子も再レンダリング

親の state を更新すると、子も再び実行される

親のカウント: 0

子コンポーネント

この子は props を受け取っていません。

React は子の関数をもう一度実行して、その結果を比べます。 props が同じでも、親が再び描き直されるときは子も動きます。

parent-re-renders-child.tsx

"use client";

import { useTrackDemoRender } from "@/components/lesson/demo-card";
import { Button } from "@/components/ui/button";
import { useState } from "react";

function Child() {
	useTrackDemoRender();

	return (
		<div className="rounded-xl border border-slate-200 bg-slate-50 p-4 text-sm">
			<p className="font-semibold">子コンポーネント</p>
			<p>この子は props を受け取っていません。</p>
		</div>
	);
}

export function ParentRerendersChild() {
	const [count, setCount] = useState(0);

	return (
		<div className="flex flex-col gap-4">
			<div className="rounded-xl border border-slate-200 bg-slate-50 p-4">
				<p>親のカウント: {count}</p>
				<Button size="sm" onClick={() => setCount((current) => current + 1)}>
					親を更新する
				</Button>
			</div>
			<Child />
		</div>
	);
}

props の変化はきっかけではない

function Child() {
  useTrackDemoRender();
  return <p>私は props を受け取っていません。</p>;
}

function Parent() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <button onClick={() => setCount((current) => current + 1)}>
        親を更新する
      </button>
      <Child />
    </div>
  );
}

この例では、子が受け取る値はありません。 それでも親が更新されれば、子の関数は再び呼ばれます。

parent-re-renders-child.tsx

"use client";

import { useTrackDemoRender } from "@/components/lesson/demo-card";
import { Button } from "@/components/ui/button";
import { useState } from "react";

function Child() {
	useTrackDemoRender();

	return (
		<div className="rounded-xl border border-slate-200 bg-slate-50 p-4 text-sm">
			<p className="font-semibold">子コンポーネント</p>
			<p>この子は props を受け取っていません。</p>
		</div>
	);
}

export function ParentRerendersChild() {
	const [count, setCount] = useState(0);

	return (
		<div className="flex flex-col gap-4">
			<div className="rounded-xl border border-slate-200 bg-slate-50 p-4">
				<p>親のカウント: {count}</p>
				<Button size="sm" onClick={() => setCount((current) => current + 1)}>
					親を更新する
				</Button>
			</div>
			<Child />
		</div>
	);
}

理解できたか確かめる

確認クイズ

子コンポーネントの props が同じでも再レンダリングされるのはどちらの場合?

確認クイズ

親が再レンダリングするとき、子はどうなりますか?

parent-re-renders-child.tsx

"use client";

import { useTrackDemoRender } from "@/components/lesson/demo-card";
import { Button } from "@/components/ui/button";
import { useState } from "react";

function Child() {
	useTrackDemoRender();

	return (
		<div className="rounded-xl border border-slate-200 bg-slate-50 p-4 text-sm">
			<p className="font-semibold">子コンポーネント</p>
			<p>この子は props を受け取っていません。</p>
		</div>
	);
}

export function ParentRerendersChild() {
	const [count, setCount] = useState(0);

	return (
		<div className="flex flex-col gap-4">
			<div className="rounded-xl border border-slate-200 bg-slate-50 p-4">
				<p>親のカウント: {count}</p>
				<Button size="sm" onClick={() => setCount((current) => current + 1)}>
					親を更新する
				</Button>
			</div>
			<Child />
		</div>
	);
}