🎃

useEffect has amissing dependencyのwarningを解消する

3 min read

こんにちは

マッケイです。

まとめまで書き終わった後に突如ページが消えて、まっさらのページを見ながら、それでもなお不屈の精神で書き上げた記事になります。

はじめに

僕が運営するReact Bootcampというコミュニティにて、useEffect has amissing dependencyというwarningを解消したいという声を聞きました。

僕自身も体系だった情報がないかと探したところ、見当たらなかったのでこの記事を執筆しました。

なぜwarningが発生する?

そもそもなぜこのwarningが発生しているのでしょうか?

このwarningを出している本体は、ESLintです。

ESLintとは

ESLintが、useEffect関数に対して「依存関係おかしいでお前」と注意を出してくれています。

このwarningが出るタイミングは以下のような関数を書いた時です。

useEffect(()=>{
  something(dependency, otherDependency);
},[]);

useEffect内で依存関係を引き起こす変数(概ねuseStateの変数)を使用しており、かつuseEffectの第二引数に空配列を指定した場合、このwarningが発生します。

useEffectは、第二引数に指定されたステートの変更を検知して、useEffect内の関数を実行するという動作をします。

その中で、依存関係を指定しないまま関数を記述していると丁寧にESLintが「依存関係を解決してないで」と注意をくれます。

とは言っても、コンポーネントがマウントされた時に一回だけ使用したいというユースケースもあります。

そんなとき、このwarningは少しうるさいですね。

warningを解消する

ではこのwarningを解消する方法を見ていきます。

warningの解消には、3つの方法があります。

  1. 依存関係を解消する
  2. 特定の行だけESLintのルールを無効にする
  3. コード全体でESLintのルールを無効にする

依存関係を解消する

当然ながら、注意を受けている依存関係を全て解消すればwaningは消えます。

useEffect(()=>{
  something(dependency, otherDependency);
},[dependency, otherDependency]);

しかし、これではdependencyotherDependencyが更新されるたびにuseEffectが実行されます。

今回のユースケースでは使えません。

特定の行だけESLintのルールを無効にする

そこで、ESLintのルールを部分的に無効にすることで、この問題を解決できます。

useEffect(()=>{
  something(dependency, otherDependency);
// eslint-disable-next-line react-hooks/exhaustive-deps
},[]);

// eslint-disable-next-line react-hooks/exhaustive-depsというコメントを記述した直下のコードは、warningを出しているコードのルールを無効にできます。

見てわかる通り、このwarningreact-hooks/exhaustive-depsというESLintのルールで吐き出されています。

よって、そのルールを無効にすることでwarningを止めることができます。

しかし、この方法では必要な全ての箇所でコメントを記述しなければならず、なかなかに骨の折れる作業です。

コード全体でESLintのルールを無効にする

それならばコード全体でそのルールを無効にしてしまえばいいのではないかということで、ESLintのルールを書き変えて、warningをコード全体から排除します。

普通であれば、ESintが有効な場合、ルートディレクトリに.eslintrcなりeslint.jsonなりのESLintのconfigファイルが生成されています。

しかし、create-react-appで作成されたプロジェクトではこのconfigファイルがありません。

にも関わらず、ESLintが有効になっているのがcreate-react-appのややこしいところです。

create-react-appでは、ESLintの設定がpackage.jsonに記述されます。

そのため、ESLintのルールを書き換えるときは、package.jsonのESLintの記述を変更する必要があります。

package.json
{
  ...
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ],
    
    // NEW!!!!
    "rules": {
      "react-hooks/exhaustive-deps": "off"
    }
  },
  ...
}

eslintConfigという項目に対して、rulesを新規に追加しています。

これで、コードベース全体でuseEffect has amissing dependencywarningを解消できます。

この方法は、全てのコードでexhaustive-depsのルールを無視することになります。
ESLintの注意を無視するので、間違ったコードを書いていてもスルーしてしまう可能性もあります。
しかし、あくまで個人の見解ですが、useEffectを使用する際には2つ以上の依存関係を含むステートを使用することが多く、その中では、全ての依存関係を含む必要がない場合が多いです。
そのため、結局// eslint-disablewarningを消します。
結局ほとんどの場所で必要になるのであれば、もはやルールとして機能させる必要がないので排除してしまっています。

また、package.jsonにESLintの設定を書くのが気持ち悪いという方は、.eslintrcをルートディレクトリに作成し、ESLintのルールをそこに書くこともできます。

.eslintrc
{
  "extends": ["react-app", "react-app/jest"],
  "rules": {
    "react-hooks/exhaustive-deps": "off"
  }
}

もちろんpackage.jsonから、eslintConfigを消すことをお忘れなく。

まとめ

useEffect has amissing dependencyのwarningを解消する方法をご紹介しました。

ESLintは便利な反面おせっかいなところも見え隠れします。

特に自動生成される系のルールは知らない間にたくさんのルールが設定されているので、これを機にどのようなルールが設定されているかを見てみるのも面白いかもしれません。

Happy Hacking😎

Discussion

ログインするとコメントできます