解决在同一个应用程序中有多个 React 副本

新手上路,请多包涵

我正在本地开发一个 React 模块。为此,我使用 npm link 链接我的模块。模块已成功导入,但挂钩在模块内部失败。它抛出以下错误:

挂钩调用无效。钩子只能在函数组件的主体内部调用。这可能由于以下原因之一而发生: 1. 您可能有不匹配的 React 版本和渲染器(例如 React DOM) 2. 您可能违反了 Hooks 规则 3. 您可能有多个 React 副本相同的应用程序有关如何调试和修复此问题的提示,请参阅 https://reactjs.org/link/invalid-hook-call

检查 React 文档 中的建议,我可以确认我的应用程序正在使用 React 的重复版本,因为以下代码返回 false:

 // node_modules/mymodule/src/index.js
export { default as ReactFromModule } from 'react'

 // src/index.js
import React from 'react'
import { ReactFromModule } from 'mymodule'
console.log(React === ReactFromModule) //false

这个问题 充满了建议,但它们令人困惑。我该如何解决?

注意:我没有违反钩子规则,错误仅在从应用程序导入模块时出现。

原文由 Rashomon 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.3k
2 个回答

在您正在开发的模块中,将冲突的包添加到 peerDependencies (并将它们从 dependenciesdevDependencies 中删除):

   // package.json
  "peerDependencies": {
    "react": "16.13.1",
    "react-dom": "16.13.1"
  },

在您的模块中执行 npm install

现在将 reactreact-dom 添加到 模块 的 webpack 配置中,作为 externals 。这些包不应包含在模块的捆绑包中(使用该模块的应用程序将提供它们):

 // webpack.config.js
module.exports = {
    /*
    rest of config...
    */
    output: {
        filename: "index.js",
        pathinfo: false,
        libraryTarget: 'umd', // In my case, I use libraryTarget as 'umd'. Not sure if relevant
    },
    externals: {
        // Use external version of React
        "react": {
            "commonjs": "react",
            "commonjs2": "react",
            "amd": "react",
            "root": "React"
        },
        "react-dom": {
            "commonjs": "react-dom",
            "commonjs2": "react-dom",
            "amd": "react-dom",
            "root": "ReactDOM"
        }
    },
};

然后,在构建模块之后,您可以 在应用程序中 检查两个版本现在是否相同:

 // node_modules/mymodule/src/index.js
export { default as ReactFromModule } from 'react'

 // src/index.js
import React from 'react'
import { ReactFromModule } from 'mymodule'
console.log(React === ReactFromModule) // true :)

原文由 Rashomon 发布,翻译遵循 CC BY-SA 4.0 许可协议

Adding react and react-dom as peerDependencies in the package.json didn’t work for me.

我不得不在 webpack 配置文件中添加一个别名:

 // webpack.config.js
resolve: {
  alias: {
    react: path.resolve('./node_modules/react'),
}

原文由 L. Pier Roberto 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题