LoginSignup
1
1

useEffectのreturn: cleanupを忘れると、💸お金がなくなるかも!😱

Posted at

こんにちは、株式会社グロービスのフロントエンドエンジニアです :wave:
イベントリスナー関連のcleanupコードの重要さについて少し書きたいと思います!

問題の説明

最近、開発しているサービスで、外部APIの導入で下記の現象が起きてました:

image.png

ページを変わるたびに、同じリクエストがどんどん増えてきました

  1. Topページを視聴すると: 1つリクエスト
  2. 違うページに行くと:2つ同じリクエスト(合計3つ)
  3. Topページを視聴すると:3つ同じリクエスト(合計6つ)

つまり、3つリクエストの代わりに、急に6つになりました!

🚨 各リクエスト = 💸💸💸 🚨

問題を起こしたコード

Quiz: 下記のコードでは、どういう問題がありますでしょうか?

useEffect(() => {
  const fetchWelcomeMessageFromPaidAPI = () => { /*... logic ...*/ }
  document.addEventListener('api-initialized', fetchWelcomeMessageFromPaidAPI);
}, [/*... dependencies ...*/]);

React.useEffectの復習

Quizの答え知るなら、次の段落に進んで大丈夫です。
そうじゃなければ、少し復習しましょう。

React.useEffectを使ったことがありますか?

useEffect(() => {
  // some logic

  return () => {
    // cleanup
  };
}, [/* dependencies */]);

上記のhookを知らない方へ、Reactのドキュメンテーションがおすすめです。

useEffectの中のreturnの意味を復習しましょう:

  • returnの役割:cleanup コード (例えば、追加されたイベントリスナーの削除など :smiley: )
  • returnの実行タイミング:
    • コンポーネントはunmountされる時
    • useEffectが実行される時

問題解決

useEffect(() => {
    const fetchWelcomeMessageFromPaidAPI = () => {
        //... some logic ...
    };
    document.addEventListener('api-initialized', fetchWelcomeMessageFromPaidAPI);

    return () => {
        document.removeEventListener('api-initialized', fetchWelcomeMessageFromPaidAPI);
    };
}, [/* dependencies */]);

cleanup 関数を追加することで、問題が解決されました。

幸いなことで、早い段階で気づかれて、今回特に損がなかったが、このような片付けはどれだけ大事かということを伝わっている例だなと思いました。

どうやってこのようなleakを防ぐか?

  • イベントリスナーを使うなら、必ずブラウザーのdev toolsコンソールで同じイベントリスナーの数が増えていないか確認しましょう (getEventListeners(domElement)
  • cleanupのreturn関数を忘れないこと 🤗
  • 自分でイベントリスナーを追加しなくても、他のエンジニアのPRをちゃんと確認すること

このように確認がちゃんとできたら、今回の問題はなかったでしょう!😅

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1