React が peerDependencies に入っているローカルパッケージを使うと動かなくなる問題

ローカルの React ライブラリに依存すると、下記のエラーがでる問題の対策です。

Uncaught Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component.

背景

React を使った Web アプリの開発において、コンポーネントを別パッケージとして作ることができます。このとき、いちいち自作のパッケージを npm publish していると面倒なので、ローカルファイルを参照するように package.json に指定すると便利です。

  "dependencies": {
    "bar-lib": "file:../bar-lib",
  }

このとき、react は bar-lib の peerDependencies と、foo-app の dependencies に指定されていて、foo-app は webpack でビルドを行っているとします。 また、bar-lib に定義されたコンポーネントは内部で Hooks を使っているとします。

foo-app で bar-lib に定義されたコンポーネントを利用すると、下記のようなエラーがでます。

Uncaught Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component.

ローカルパッケージ側の node_modules に入っている react を読み込んでいて、利用側の react と別のインスタンスになるために発生しています。

https://github.com/facebook/react/issues/15812

採択

webpack.config.js に alias を追記します。

  resolve: {
    alias: {
      react: path.resolve("./node_modules/react"),
    },
  },

こうすると、webpack が react パッケージを解決するときに、ライブラリ側 (bar-lib/node_modules/) のものではなく現在のパス (foo-app/node_modules/) の react を参照するようになります。

これで利用される react のインスタンスが一つになりエラーが出なくなります。