はじめに
Reactを書いてるとみなさんも、一度は下記エラーを見た事があると思います。
エラーメッセージ内容
React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render.
ReactのHooksのルールに 「フックを呼び出すのはトップレベルのみ」 があります。
今回の例では、if文中のuseEffect
の定義がルールに抵触しているため、エラーが発生しました。
なるほど🤔 ルールに抵触しているからエラーが出るのは理解できた。
ただ、なんでこんなルールが定義されているの?ルールを定義してまでエラー検知しているのには、仕組み的に何か理由があるはず。ただ、なんでかはさっぱりわからん。。。
なので、今回は 「React Hooksはなぜトップレベルに書かないといけないのか。」 の理由を解き明かしていこうと思います!!
Hooksのルール確認
Hooksのルールは公式に記載がありました。下記に示します。
フックを呼び出すのはトップレベルのみ
フックをループや条件分岐、あるいはネストされた関数内で呼び出してはいけません。代わりに、あなたの React の関数のトップレベルでのみ、あらゆる早期 return 文よりも前の場所で呼び出してください。これを守ることで、コンポーネントがレンダーされる際に毎回同じ順番で呼び出されるということが保証されます。これが、複数回 useState や useEffect が呼び出された場合でも React がフックの状態を正しく保持するための仕組みです(興味がある場合はページ下部で詳しく説明しています)。
コンポーネントがレンダーする際の順序を保証するため、トップレベルにおく必要があるようです。
ふーん、わけわからん💦💦💦色々わけわからないけど、大きく3点わからない。
- トップレベルにおくと、なぜ順序が保証されるのか?
- そもそも順序とは何か?
- 順序という位だから、複数要素あると思うが要素とは何か?
わからないことはわからないので、1つづつ理解を進めていこうと思います。
React Hooksには他にもあります。
本件には直接紐づかないので、下記に補足します。
React Hooksの他ルール
フックを呼び出すのは React の関数内のみ
フックを通常の JavaScript 関数から呼び出さないでください。代わりに以下のようにします。✅ React の関数コンポーネント内から呼び出す。
✅ カスタムフック内(次のページで説明します)から呼び出す。
このルールを守ることで、コンポーネント内のすべての state を使うロジックがソースコードから間違いなく参照可能になります。
公式の解説
公式では、下記の解説がありました。以下、引用です。
ごたごた書くよりも、公式の解説を乗っけておきます。
→あー、なるほど🤔完全に理解した。。。とは全然ならないですね。🥲
順番があるのは理解したけど、なぜ順番通りに理解しないといけないのか。
ChatGPTに質問した所、筋の通った回答が返ってきたので、記載します。
ChatGPTの回答
現実世界の出来事である 料理 を例に解説しております。
useStateが材料、useEffectが調理、useContextが味付けと置いたとする。
この時、材料→調理→味付け の順番を必ず守らなくてはなりません。
材料がないのに調理や味付けはできないし、調理できてないのに味付けはできないです。
ごく当たり前のことです。
この当たり前の考え方をReactの世界に持ってきた所、ReactHooksではトップレベルに書きましょうというルールができたとのことです。
現実世界の料理と同じように、ReactHooksも順序を守る必要がある。
そのために、条件分岐やループ、ネストされた関数内で呼び出す事ができない。
まとめ
React Hooksは順序を保証するため、トップレベルで書かないといけない。
参考文献