React:memo化
2026年4月11日React Compiler
*重要:
React Compilerを使うと自動的に最適化してくれるのでmemo化を手動で実装する必要が無くなる。
新規コードの場合はmemo化を意識したコードを書かなくていいので、memo化を覚えるコストは減ると考えられる。
Nextjs:
// next.config.ts
const nextConfig: NextConfig = {
reactCompiler: true,Tanstack-Start:
// vite.config.ts
const config = defineConfig({
plugins: [
viteReact({
babel: {
plugins: ["babel-plugin-react-compiler"],
},
}),
],memo化
Reactでは親コンポーネントが再レンダリングされると子コンポーネントも再レンダリングされるが、memo化により「再レンダリング」を制御することでパフォーマンスを上げる。
memo化自体にもコストがかかる。
memo()
export default function Parent({items}) {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(count + 1)}>+1</button>
<List items={items} /> // 重い
</div>
);
}
const List = React.memo(({ items }: { items: string[] }) => {
console.log("rendered");
return (
<ul>
{items.map((i) => (
<li key={i}>{i}</li>
))}
</ul>
);
});親コンポーネントの状態が代わると、親の状態と関連が無い
<Lists />コンポーネントも再レンダリングされるが、React.memoを使うと再レンダリングされなくなる。
useCallback()
useCallback() は「状態」ではなく「関数」をpropsとして渡す場合に使う。使い方としてはmemo()と組み合わせて使う
export default function List() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => console.log("test"), []);
return (
<ul>
<button onClick={() => setCount(count + 1)}>+1</button>
<Item
onClick={handleClick}
/>
</ul>
);
}
const Item = React.memo(({ onClick }: { onClick: () => void }) => {
console.log("rendered");
return (
<li>
<button onClick={onClick}>x</button>
</li>
);
});<Item />側にReact.memoがあれば親コンポーネントで状態の変化が起きても再レンダリングは防げると考えるかもしれないが、子に渡しているhandle関数が親のレンダリング毎に新しい参照を作るので<Item />は再レンダリングされる。useCallback()で関数を囲むことで関数の参照を固定できる為、関数を渡した子コンポーネントの再レンダリングを防げる。
参照(Reference):
JavaScript では オブジェクトや配列、関数は値ではなく「メモリ上の場所」を指している。そのため再レンダリング毎に中身は同じでも新しい関数として扱われる。
useMemo()
useMemo() はuseCallback()の値・オブジェクト版。 useCallback()と同様に子コンポーネントに値を渡して、子の再レンダリングを防ぐ使い方をする。子コンポーネントに関係なく、重い計算を再実行させないような使い方もできる。
const Parent = () => {
const [count, setCount] = useState(1);
const memorizedValue = useMemo(() => {
console.log("useMemo");
return count * 100
}, []);
return (
<div>
<button onClick={() => setCount(count + 1)}>+ {count}</button>
<Memo value={memorizedValue} />
</div>
);
};
export default Parent;
export const Memo = React.memo(({ value }: { value: number }) => {
console.log("rendered");
return <div>{value}</div>;
});