Open7

reactでmonorepoすると"Invalid hook call"なエラーが出る問題

akaboshinitakaboshinit

経緯:

  1. 稼働している、既に作られていたreact-next製サイト(以下,Aサイト)があった

  2. 1のプロダクトを分割することになり、"1の機能を使いたい・機能追加もあり"となりmonorepoを構築することが決定

  3. 1のrepositoryをmonorepo化して、新たなreact-next製サイト(以下,Bサイト)をその中に配置する方向にして共通記述は"shared"dirに置く設計
    :monorepoツールとしてはturborepo(& npm workspace)という、あまり複雑なことをしない感じ

だいたいこんな感じ
├─apps
│ ├──siteA
│ │   └─package.json
│ └──siteB
│     └─package.json
├─packages
│  └─shared
│     └─package.json
└─package.json
akaboshinitakaboshinit

もっと色々経緯あるけど簡単に書くと

  1. 一旦siteAをmonorepoのための特別な操作なしでsiteBの開発スタート

通常ならsiteA-package.jsonの"dependency"など依存をroot-package.jsonに移動して
そのroot-package.jsonで使われている依存を使ってsiteBを構築した方が良い(siteBでしか使わないものをsiteB-package.jsonに記述する)

そうなった理由:siteB構築のスピードが大事だったのと一定期間siteAは触らないことがわかっていた。今思えば、そうだとしても上記の操作をすべきだったと後悔してる。次は間違えない

  1. siteBを作り込んでいった(1ヶ月くらい)・一旦リリースレベルまで達したので自分のタスクは終了

そのsiteB作っている時点でsiteAでbuildエラーが出ていた。それはわかっていたけどsiteBのスピードのために無視

  1. そのエラー解消するために今色々してます
akaboshinitakaboshinit

siteAをnpm run dev(next dev)をしたらこんなエラーが

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
DeepL訳
エラーです。無効なフック呼び出しです。フックは、関数コンポーネントのボディの内部でのみ呼び出すことができます。これは、次のいずれかの理由で発生する可能性があります。
1. React とレンダラー(React DOM など)のバージョンが不一致である可能性があります。
2. フックのルールを破っている。
3. 同じアプリに複数のReactのコピーがある可能性
この問題のデバッグと修正方法については、https://reactjs.org/link/invalid-hook-call を参照してください。

エラー序盤にhooksがどうとか書いてあるので???ってなるけど
理由として挙げられている1,3がmonorepo起因で起きていそうとわかる

akaboshinitakaboshinit

自分のログとか出したいけど
ミスってターミナル消えてしまったので同じことやった人出してほしい...

akaboshinitakaboshinit

https://ja.reactjs.org/warnings/refs-must-have-owner.html#multiple-copies-of-react
nextのエラー出るけど"You might have more than one copy of React in the same app"の部分についてreactの公式サイトに載ってた

npm ls react

これをsiteA,siteBで行うと依存パッケージの依存になっているreactのバージョンがぞろぞろ出てくる
どれかがrootのバージョンとズレてるとエラーが出る模様

ほとんどrootのバージョンと一緒の出てくるけどどれかバージョンがズレてる場合なら
そのバージョンをrootのバージョンに合わせれば解決する

akaboshinitakaboshinit

自分の場合は"react-zoom-pan-pinch"のみが古いreactバージョンになっていた
rootはちなみにreact18系で"react-zoom-pan-pinch"の方を調べるとreact18対応がmergeされていない状態らしい
https://github.com/prc5/react-zoom-pan-pinch/issues/292

そのissueのコメントにあったreact18対応のforkがあるらしい
https://github.com/prc5/react-zoom-pan-pinch/issues/292#issuecomment-1158079146

https://www.npmjs.com/package/@pronestor/react-zoom-pan-pinch

元のパッケージと完全互換になっているため

  1. npm i @pronestor/react-zoom-pan-pinch
  2. "react-zoom-pan-pinch"を"@pronestor/react-zoom-pan-pinch"置換
    これだけで記述は問題なかった

その上で"npm run dev"でエラー出なくなった!!!

akaboshinitakaboshinit

結論:
monorepo内のどこかのパッケージでreactの依存バージョンがズレているとエラーが出る
ズレている該当パッケージをアップデートするなどしてreact依存バージョンを合わせるとエラー解決する