3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

カスタムフックを 2重処理して React に怒られた話【Minified React error #321】

Last updated at Posted at 2023-09-27

はじめに

React制のサイトを修正して本番環境にホスティングし、動作検証していると下記のエラーが表示されました。
ややこしいことに、開発環境では何も警告など表示されず本番環境でのみ出てきたのです
もし筆者と似たような方がいればエラー文章の検索でヒットして手助けできれば幸いです。

Uncaught Error: Minified React error #321; visit https://reactjs.org/docs/error-decoder.html?invariant=321 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.

デバックするにあたって日本語の情報はいくつかあったのですが自身の現象には該当せず解決に少し苦労しました。

デバック時に目を通した日本語の記事を貼っておきますので必要に応じてチェックしてみてください!

エラーの原因

(おそらく)自身で用意したカスタムフックの2重処理が原因でした。すみませんでした。

ページ移動後のブラウザバック時に発生していた

当該エラー(#321)は、具体的にはページ遷移のクリックイベントを行った後のブラウザバック時に発生していました。ルーティングにはReact Routerを使っており、サブページからTOPページへ移動する際にLinkをクリックするとページ移動でき、ブラウザバックも問題なく行えるなど期待する挙動はしてくれるものの当該エラーが表示される、といった次第です。

試行錯誤して時間を浪費

エラー文を読むと詳しい情報が記載されたページへのリンクを促されているのでそちらで情報を確認。

(...中略)先ほど発生したエラーの全文は次のとおりです:無効なフック呼び出しです。フックは、関数コンポーネントの内部でのみ呼び出すことができます。これは、以下のいずれかの理由で発生する可能性があります: 1. Reactとレンダラー(React DOMなど)のバージョンが不一致である可能性がある 2. フックのルールを破っている可能性がある 3. 同じアプリにReactのコピーが複数ある可能性がある この問題のデバッグと修正方法のヒントについては、https://reactjs.org/link/invalid-hook-call を参照してください。

「詮索範囲が広くてなかなか絞り込めそうにないなぁ」と思いながら、とりあえずトリガーとなっているLinkまわりの検証を進めました。

この時は自分のReact Routerの設定ミスだろうと思っており、
「コード修正 → ビルド → テストサーバーへアップ」という流れで検証を進めていました。
なんとも非効率です(泣)。

しかし、原因はReact Routerの設定ミスでも何でもなく自身の作ったカスタムフック
哀れな筆者は時間を浪費していきました……。

自身の過ちに気づく

今回話している React制のサイトでは、Contextを使用して各ページ用のStateを管理していました。

各ページ用のStateを作っている理由はtitlemetaなどhead関連の情報をState別(ページ別)に用意して書き換えるようにしているためです。

TOPページ用のState変数を更新する関数をカスタムフック(以下:ChangeTopPageState)として用意し、サブページからTOPページへ移動するリンク(Link)のクリックイベントにそのカスタムフックを使用していました。
しかし、TOPページ(のコンポーネント)のuseEffect内でも TOPページ用のState変数の更新関数(セッター関数) を実行していました。

この筆者の愚かな行為によって、

  • 「クリックイベントでのカスタムフック(ChangeTopPageState)でTOPページ用のState変数を更新」 →
  • 「ページ遷移後のTOPページ(のレンダリング後に)同様の処理を実行」 →
  • 「ブラウザバック時にState更新関連の不具合発生?」

という状況になっていたのです。

ようやく、Linkのクリックイベントに指定していたChangeTopPageState(=自身の過ち)に気付いた筆者はクリックイベントをすべて削除。テストサーバーでエラーが表示されないことを確認し、本番環境へホスティングして同様の確認が取れました!無事解決!

解決はしたものの……「あれ?でもTOPページのuseEffectに依存配列を記述していないし、これだけなら『State変数が単に2回変更されるだけ』なんじゃないの?」とか「ブラウザバック時にState更新関連の不具合が出ているってこと?」と思ったりもしています。
はっきりした原因を言及できず申し訳ないのですが、おそらく先述したエラー文の「2番目に該当」したのでは?と思っています。

2.フックのルールを破っている可能性がある

または、上記「筆者の愚かな行為」で説明した以下フロー

  • (TOPページ用のState変数を更新するカスタムフック)ChangeTopPageState実行 →
  • TOPページ(のコンポーネント)のuseEffect内でも同様の処理

というこれらの過程がReactのライフサイクルに支障をきたしたのかもしれません。

まとめ

当たり前なことを言うかもですが、
React のように機能別に切り分けて組み立てていくコンポーネントベースのものは

  • どこで何を使っているか(しているか)
  • ソレ(State や Hook etc...)はそこで使用するのが適切なのか
  • (Reactでは)再レンダリングへの考慮

といった意識・注意、コード(コンポーネント)管理が大事だなと実感しました。

ここまでお読みいただきありがとうございました。
本記事が誰かのお役に立てれば嬉しいです。

3
0
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
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?