2021/10/16
はじめに
コンポーネントを含む自作ライブラリを npm に公開しようとして,ローカルインストールをした.
それを実行しようとしたところ,下に載せるエラーが発生した.
おそらく,ローカルインストールをしておらず同様のエラーが出た場合は,エラー文に記載のとおりにReact 公式ページを参考にするのが良いと思われる.
TL;DR
npm pack
によりパッケージングnpm install
でプロジェクトディレクトリではなくxxx.tgz
をインストール
エラー
まず前提として,npm intsall
でディレクトリパスを指定すると,該当ディレクトリのpackage.json
にある情報を元にローカルインストールされる.
$ npm install ./dir
このインストール方法を使って,React コンポーネントを含むライブラリをインストールし,アプリを起動しようとしたところ,以下のエラーが出た.
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.
何の問題なのか?
「2 つの React」となっていることが問題である.
以下簡単のため,自作したライブラリをライブラリ,ライブラリをインストールして使うアプリをアプリと呼ぶことにする.
「2 つの React」とは,react library が2つ存在していることを意味しているようである.
上述したローカルインストールの方法の挙動を調べてみた.方法としては, 1)通常のインストールの import 元を確認, 2)npm install ./dir
の import 元を確認をした.
2点の確認の結果が以下となった.
~/node_modules/xxx
./dir/dist
(ちなみに,package.json
には./dist
をパスにするよう設定してある)
この結果を踏まえると,~/node_modules/
以下に直接インストールされるわけではなく,参照しているようである.
この時,./dir/dist
にあるファイルの import が./dir/node_modules
なのではないか.
以上が,問題点の分析となった.
解決策?
npm link
という方法もあるようだが,これによる解決が根本的な解決には思えなかったため,別の方法を模索した(参考).
npm link
によって,インストール先をアプリと一致させることで,「2 つの React」問題を解消するという内容であった.
模索した結果
ライブラリを参照じゃないインストールすることが問題解決のための目的となる.
npm pack
を使うと,xxx.tgz
という名前でパッケージングされる.
そして,そのxxx.tgz
をインストールする.
$ npm install ./dir/xxx.tgz
package.json
内のインストール情報としては,file:./dir/xxx.tgz
となるが,import 元は./node_modules/xxx
となっており,おそらく,xxx.tgz
が./node_modules/
直下にモジュールを展開しているようである.
エラーが出ずに望まれる挙動だったということは,「2 つの React」状態が解消したため,同じreact
を import できている事になるようだ.
おわりに
StackOverflow や Github の React リポジトリの Issue には同じ解放がなかったのだが,npm pack
にたどり着けてよかった.
これで,npm パッケージ開発が捗りそうである.