まだalphaリリース(v16.7.0-alpha)のHooksを使っていたらハマった。
『Hooks can only be called inside the body of a function component.』とエラーバウンダリーの画面で怒られてしまう。
状況
怒られる。
ディレクトリ図はこういう感じで、ライブラリ開発現場(親)の中にexample(子)ディレクトリがあって、子は子で別途package.jsonとnode_modulesを抱えているという状況。
. ├── example │ ├── node_modules │ ├── package.json │ └── src ├── node_modules ├── package.json └── src
なおexampleディレクトリはライブラリのデモページのためのディレクトリ。
この構成は
このcreate-react-libraryというボイラープレートの構成をベースにしている。
Issue
Dan氏が想定の挙動だよ〜ってコメントしている
エラーの原因はライブラリが参照しているReactと子ディレクトリで参照しているReactが異なるためらしい。
- 子ディレクトリで親階層にあるライブラリを利用はするけど作成中のライブラリにLinkを貼っているだけ
- ライブラリが参照するのは
/node_modules/react
- ライブラリが参照するのは
- 子ディレクトリのプロジェクト自体が利用するreactはどこ
/example/node_modules/react
ようは参照しているreactのインスタンスが異なるとダメっぽい。
解決方法
このIssueに解決策が書かれていて、子のpackage.jsonのdependenciesにあるReactを親のnode_modulesに指定してやればよい
"dependencies": { . . . "react": "link:../node_modules/react", "react-dom": "link:../node_modules/react-dom" }
これでyarn -fあるいはrm -rf node_modules/ && yarnてな具合に依存モジュールを再インストールすればOK
子プロジェクトでのReactは親階層である/node_modules/reactを参照するようになるので、同一インスタンスのものが参照されるようになって解決。
lerna あるいは yarn workspace でも解決できそう
参照するReactのインスタンスが異なるのが原因なので、それを回避できればOKっぽい。
lernaやyarn workspaceを用いると単一の共通したnode_modulesを利用できるので、解決できるはず。
実際自分も最初は↑の単純に親階層にlinkさせる方法にたどり着けなくてyarn workspaceを試していた。
手元でHooksの動作まではうまく行ったのだけど、自分の環境ではRollup.jsでバンドルしていた箇所がどうも壊れてしまって別問題をはらんでしまったのでやめた。(おそらくnode_modulesが複数箇所に分散されるのでそれをRollup.jsが解決できずでなにかしらコケてしまった)
rollup+yarn workspaceでうまくいったよ〜っていう人がいれば教えて欲しい。
余談あるいはバージョニング問題
余談だけど、本件でハマっているときに出くわした別問題で、Reactのv16.7.0にはHooks機能が削られているという罠があった。
"dependencies": { "react": "^16.7.0-alpha.2", "react-dom": "^16.7.0-alpha.2" }
最初Hooksを試すためにalpha2をインストールしていて、exactオプションなしでインストールしたからチルダ(^)ありになっていた。
semver的にこの状態でyarn upgradeするとv16.7.0のStableに更新されてしまうけど、なんとv16.7.0ではHooksはごっそり削られていた。
v16.7.0-alpha.2- Hooksあり
v16.7.0- Hooksなし
Stableリリースでたしかに『Hooksはまだ』とは言われていたけど、alphaの内容継承していると考えるのがなんとなく自然なはずで、upgradeしてから急にHooksが動かなくなってハマってしまった。
yarn add --exact react@16.7.0-alpha.2 react-dom@16.7.0-alpha.2でexact指定しておく必要があった。
こうするとチルダなしでpackage.jsonに書き込まれるので、依存関係のアップグレードをしてもReactがStableに上がることはない。
いろいろ大変という気持ち。
それはそうと見よう見まねで"link: ~"って書いてるけどこれのリファレンスが見つけられない。"file: ~"のリファレンスなら出てくるけど違いが知りたい。