【入門編】 useCallbackフックによる関数のメモ化 – React実践ガイド

やあ!Reactの世界へようこそ。フロントエンドの現場で日々コードと格闘しているチーフアーキテクトです。

Reactを触り始めると、必ずと言っていいほど「再レンダリング」という壁にぶつかりますよね。「あれ?何も変えていないはずなのに、なぜか子コンポーネントが何度も動いている…?」なんて経験、誰にでもあります。

今日は、そんなモヤモヤを解消する魔法の杖、`useCallback`についてお話しします。難しく考える必要はありません。一緒に紐解いていきましょう。

—

1. なぜ「関数」がメモ化(記憶)される必要があるの?

まず、身近な例で考えてみましょう。あなたは「おつかい」を頼まれたとします。

  • 普通の状態: お母さんが毎回「牛乳を買ってきて」と、新しいメモを渡してきます。たとえ中身が同じ「牛乳」でも、毎回新しい紙を渡されたら、あなたは「これは前のメモと同じ内容かな?」とわざわざ確認しなきゃいけませんよね。
  • useCallbackの状態: お母さんが「冷蔵庫の上のこのメモを使ってね」と、同じメモを使い回すようにします。あなたは「ああ、いつもの牛乳ね」とすぐに理解でき、無駄な確認時間を省けます。

Reactの世界でも同じことが起きています。コンポーネントが再レンダリングされるたびに、関数も「新しく作り直される」のがデフォルトです。もしその関数を子コンポーネントに渡していたら、子コンポーネントは「親が新しい関数を渡してきた!中身は同じかもしれないけど、一応更新しなきゃ!」と勘違いして、無駄に再レンダリングしてしまうのです。

`useCallback`は、「この関数は中身が変わらない限り、ずっと同じものを使い回してね」とReactに約束させるためのツールなんです。

—

2. useCallbackの基本構文

さっそく、構文を見てみましょう。

const memoizedCallback = useCallback(() => {
// ここに関数の処理を書きます
console.log(“計算します”);
}, [依存配列]); // ここに変化を監視する変数を入れます

ポイントは「依存配列(`[]`)」です。

  • `[]` が空なら:一度作ったら二度と作り直しません。
  • `[count]` のように変数を入れると:`count`の値が変わった時だけ、関数を新しく作り直します。

—

3. 実践!コードで見てみよう

例えば、「ボタンを押すと増えるカウンター」と「入力エリア」がある画面を想像してください。

import React, { useState, useCallback } from ‘react’;

// 子コンポーネント:React.memoで包むことで、propsが変わらない限り再レンダリングしない
const ChildButton = React.memo(({ onClick, children }) => {
console.log(`${children} がレンダリングされました`);
return ;
});

export default function CounterApp() {
const [count, setCount] = useState(0);
const [text, setText] = useState(“”);

// useCallbackを使わないと、textを打つたびにこの関数が新しく作られ、
// ChildButtonが不必要に再レンダリングされてしまいます。
const increment = useCallback(() => {
setCount((prev) => prev + 1);
}, []); // countに依存させない(関数内でprevを使うテクニック!)

return (

今のカウント: {count}

setText(e.target.value)} placeholder=”何か入力してみて” />

{/ useCallbackのおかげで、textが変わってもこのボタンは再レンダリングされません /}
カウントアップ

);
}

ここで「なるほど!」ポイント

上のコードで、`setCount(count + 1)` と書かずに `setCount(prev => prev + 1)` と書いていることに気づきましたか?
これぞプロの技。`count`を依存配列に入れずに済むため、「カウントの値が変わっても関数自体は作り直さない(安定させる)」という高度な最適化が可能になるんです。

—

4. 最後に:使いすぎには注意!

ここまで読んで「じゃあ全部の関数を`useCallback`で囲めば最強じゃん!」と思ったあなた、ちょっと待ってください。

`useCallback`も、実は「メモリを確保して、依存配列をチェックして…」という小さなコストがかかります。すべての関数に使うと、逆にアプリが重くなることさえあるんです。

僕からのアドバイス:
最初は無理に使わなくて大丈夫です。まずは「子コンポーネントに渡す関数で、パフォーマンスに影響が出そうだな」と感じた時に、そっと`useCallback`を導入してみてください。

Reactの最適化は、パズルのようなものです。少しずつ、楽しみながらピースをはめていきましょう。何かわからないことがあれば、またいつでも聞きに来てくださいね。応援しています!

コメント

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