1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

useEffectの2回レンダリングを抑えるには

Posted at

ReactでuseEffectでマウントを行おうと思った時に2回useEffectが実行されたことはありませんか?

今回はその問題を解決する方法を探そうと思います。

useEffectとは

Reactコンポーネントを外部システムと同期させるためのHooksです。

Hookとは

Reactに標準で使えるようにされているstateやrefなどをクラスを書かずに使えるようになります。

外部との通信は副作用(サイドエフェクト)と呼ばれます。

Reactは純粋関数で実装することが定説となっています。
そのためコンポーネント関数は、あるprops(入力)に対して、予測可能なJSXが返ってくるようになっています。

しかし、外部のシステム、例えばAPIを叩いてリソースを取得してDOMを構築するとなるとAPIから何が返ってくるか等はReactアプリケーションのコードだけでは予測できません。

そのため、予測できない動作である副作用を引き起こすuseEffectはあまり使い回さないようにすることが推奨されています。

マウントとは

Reactを使ったブラウザの描画において、必要なコンポーネントのインスタンスとDOMノードの作成、それらをDOMを挿入するプロセスをマウントと言います。
簡単にいうとコンポーネントの初期化、コンポーネントを最初に描画することになるページの遷移時における描画プロセスのことをマウントと言います。

Reactのライフサイクルには、マウント、更新、アンマウントの3種類があると言われています。

ライフサイクルの種類 トリガー
マウント コンポーネントの初期化
更新 propsやstateの更新
アンマウント コンポーネントの破棄

useEffectを行うとこれらをまとめて行うことができるようになります。

useEffectが2回行われる理由

ReactにはStrictModeと呼ばれる機能があります。

StrictModeがオンになっているとマウントが2回行われるようになっています。

これはアプリケーションの潜在的なバグを見つけるために開発環境ではデフォルトでオンになっています。

StrictModeをオフにすることも可能ですが、毎回プロジェクトの立ち上げごとにオフにするのもめんどくさいと思うのでStrictModeがオンの状態でも問題ないコードを書くべきだと思います。

useEffectが2回行われないようにするには

クリーンアップ関数をうまく使うことで2回マウントを実行されることを防ぐことができます。

下のようにすることで一度マウントすることでignoreがtrueになり、一度しか実行できなくなります。

let ignore = false;
useEffect(() => {
  async function startFetching() {
    const json = await fetchTodos(userId);
    if (!ignore) {
      setTodos(json);
    }
  }

  startFetching();

  return () => {
    ignore = true;
  };
}, [userId]);
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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?