「useEffectの乱用」を避けよう

目次

🔰 useEffectって何?

useEffect は 「副作用(= side effect)」を扱うための仕組み(フック) です。

基本の書き方

useEffect(() => {
  // ここが「副作用」処理(エフェクト本体)

  return () => {
    // ここが「クリーンアップ」(必要なときだけ)
  }
}, [依存配列])
コンポーネントの一生 誕生 成長 消滅 マウント 画面に表示される 更新 内容が変わる アンマウント 画面から消える 例:ホームページ → ボタンクリック → 別ページへ移動 誕生 → 成長(ボタンクリック等) → 消滅

「副作用」ってそもそもなにかというと、「コンポーネントの表示そのもの(UI)とは直接関係ない処理」のこと。

  • データを取得したい
  • タイマーを使いたい
  • イベントを監視したい(スクロールとか)
  • 外部のライブラリを動かしたい

そのエフェクトは不要かも
https://ja.react.dev/learn/you-might-not-need-an-effect

副作用って何? 画面に表示する以外のこと = 副作用 2つに分けて考える 画面に表示 文字、画像、ボタン ユーザーが見るもの それ以外 データ取得、保存 = 副作用

依存配列とは?

useEffectが「いつ再実行されるか」をReactに伝えるための「リスト」

  • ページ読み込み時に1回だけデータを取得したい
useEffect(() => {
  fetch('/api/posts').then(...)
}, []) // ← 初回だけ実行
  • propsが変わったら処理を実行したい
useEffect(() => {
  console.log('userIdが変わったよ')
}, [userId])
  • 複数の変数に反応したい
useEffect(() => {
  console.log(`filter:${filter}, sort:${sort}`)
}, [filter, sort])
  • 依存配列なし(非推奨)=毎レンダー発火
useEffect(() => {
  console.log('これは毎回実行される💥')
})
  • 関数を依存にしたいときはuseCallbackでメモ化
const fetchData = useCallback(() => {
  fetch('/api/data')
}, []) // ← useCallbackで定義

useEffect(() => {
  fetchData()
}, [fetchData]) // ← 安心して依存にできる!
依存配列 = いつ実行するかの指示 配列なし useEffect(() => {}) 毎回実行 レンダリング 実行 また実行… 空の配列 useEffect(() => {}, []) 1回だけ実行 最初 実行 終わり 値が入った配列 useEffect(() => {}, [count]) countが変わったら実行 count変更? Yes → 実行 No → スキップ つまり:「いつ実行したいか」を配列で教える [] = 最初だけ、[count] = countが変わったら

実例:WordPressをヘッドレスCMSとして、コンテンツを取得してReactでフロントを表示する際に、取得した内容の目次にスムーススクロールを実装したい

なぜuseEffectを使用したか?

  • JSXじゃないから <a onClick={…} が書けない
  • HTMLが描画される前に .querySelector しても見つからないため、「描画された後」に処理したい
WordPressの目次HTML文字列
          ↓
   Next.jsで <TOCScroll content={...} />スムーススクロールのuseEffectを含むコンポーネント
          ↓
   parse()でHTMLを表示 ← ※このタイミングではイベントなし
          ↓
【useEffect発動】→ JSでイベント追加 → スムーススクロール

この記事を書いた人

目次