【问题标题】:Importing and using component from custom React Component Library results in Invariant Violation: Invalid hook call从自定义 React 组件库导入和使用组件会导致 Invariant Violation: Invalid hook call
【发布时间】:2019-10-18 22:58:35
【问题描述】:

我的工作是制作一个 React UI 工具包/组件库,以便在我们的产品内部使用。在 Storybook 上开发和展示时一切正常。

在从 create-react-app 开箱即用的通用项目中测试库时,导入和实现不使用 React Hooks 制作的组件是可以的,但一旦我们使用使用 Hooks 制作的组件 - 无效Hook Call 错误显示:https://reactjs.org/warnings/invalid-hook-call-warning.html

已经尝试了那里列出的所有内容(并阅读并尝试了页面上链接的 github 线程解决方案),并且该组件仅使用了 useRef() 并没有其他任何内容,因此我们知道没有违反任何规则,React 和 React-dom 版本已经上线迄今为止,在项目中运行 npm ls reactnpm ls react-dom 会导致 react@16.10.2react-dom@16.10.2 没有别的......所以看起来我们没有多个 React?

任何帮助将不胜感激!

这是 UI Kit 的package.json

{
    "name": "react-ui-kit",
    "version": "0.0.15",
    "description": "UI Kit",
    "main": "dist/index",
    "module": "dist/index",
    "typings": "dist/index",
    "jest": {
        "setupFilesAfterEnv": [
            "<rootDir>/setupTests.js"
        ],
        "coverageReporters": [
            "json-summary",
            "text",
            "lcov"
        ]
    },
    "scripts": {
        "test": "jest --coverage",
        "test:badges": "npm run test && jest-coverage-badges input './coverage/coverage-summary.json' output './badges'",
        "test-update": "jest --updateSnapshot",
        "lint:css": "stylelint './src/**/*.js'",
        "storybook": "start-storybook -p 6006",
        "build-storybook": "build-storybook -c .storybook -o .out",
        "generate": "plop --plopfile ./.plop/plop.config.js",
        "build": "webpack --mode production",
        "prepare": "npm run build",
        "prepublishOnly": "npm run test:badges",
        "storybook-docs": "build-storybook --docs",
        "todo": "leasot './src/**/*.js'",
        "todo-ci": "leasot -x --reporter markdown './src/**/*.js' > TODO.md"
    },
    "license": "ISC",
    "peerDependencies": {
        "prop-types": "^15.7.2",
        "react": "^16.9.0",
        "react-dom": "^16.9.0",
        "recharts": "^1.7.1",
        "styled-components": "^4.3.2",
        "styled-normalize": "^8.0.6"
    },
    "devDependencies": {
        "@babel/cli": "^7.6.0",
        "@babel/core": "^7.6.0",
        "@babel/plugin-proposal-class-properties": "^7.5.5",
        "@babel/preset-env": "^7.6.0",
        "@babel/preset-react": "^7.0.0",
        "@storybook/addon-actions": "^5.2.1",
        "@storybook/addon-docs": "^5.2.1",
        "@storybook/addon-info": "^5.2.1",
        "@storybook/addon-knobs": "^5.2.1",
        "@storybook/addon-links": "^5.2.1",
        "@storybook/addon-viewport": "^5.2.1",
        "@storybook/addons": "^5.2.1",
        "@storybook/react": "^5.2.1",
        "babel-eslint": "^10.0.3",
        "babel-jest": "^24.9.0",
        "babel-loader": "^8.0.6",
        "babel-plugin-styled-components": "^1.10.6",
        "eslint": "^6.5.1",
        "eslint-plugin-react": "^7.15.0",
        "eslint-plugin-react-hooks": "^2.1.1",
        "jest": "^24.9.0",
        "jest-coverage-badges": "^1.1.2",
        "jest-styled-components": "^6.3.3",
        "leasot": "^8.2.0",
        "plop": "^2.4.0",
        "polished": "^3.4.1",
        "prop-types": "^15.7.2",
        "react": "^16.9.0",
        "react-dom": "^16.9.0",
        "react-test-renderer": "^16.9.0",
        "recharts": "^1.7.1",
        "storybook-styled-components": "github:merishas/storybook-styled-components",
        "styled-components": "^4.4.0",
        "styled-normalize": "^8.0.6",
        "stylelint": "^10.1.0",
        "stylelint-config-recommended": "^2.2.0",
        "stylelint-config-styled-components": "^0.1.1",
        "stylelint-processor-styled-components": "^1.8.0",
        "webpack": "^4.40.2",
        "webpack-cli": "^3.3.9"
    },
    "files": [
        "dist"
    ],
}

UI 工具包的webpack.config.js

const path = require('path');

module.exports = {
    mode: 'production',
    entry: './src/index.js',
    output: {
        path: path.resolve('dist'),
        filename: 'index.js',
        libraryTarget: 'commonjs2',
    },
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /(node_modules)/,
                use: 'babel-loader',
            },
            {
                test: /\.(eot|svg|ttf|woff|woff2|otf)$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: '[name].[ext]',
                            limit: 10000,
                            mimetype: 'application/font-woff',
                        },
                    },
                ],
            },
        ],
    },
    resolve: {
        alias: {
            components: path.resolve(__dirname, 'src/components/'),
            utils: path.resolve(__dirname, 'src/utils/'),
            themes: path.resolve(__dirname, 'src/themes/'),
        },
        extensions: ['.js', '.jsx'],
    },
    devtool: false,
};

项目中如何导入和实现组件:

import React from "react";
import logo from "./logo.svg";
import "./App.css";
import { FieldLabel, Button } from "react-ui-kit";

function App() {
  return (
    <div className="App">
      <FieldLabel>THIS IS THE ONE USING the useRef Hook</FieldLabel>
      <Button>This component is totally fine without FieldLabel, this isn't using Hooks</Button>
    </div>
  );
}

export default App;

【问题讨论】:

  • 您在使用npm link 吗?您的项目在react@16.10.2 上运行,而库在16.9.0 上运行。如果您使用npm link,这将导致错误,因为捆绑器将看到两个反应版本。
  • 不,我们没有使用npm link,我们的库是在 npm 上私下发布的,所以我们从那里安装库。
  • 一个快速的解决方案是在你的项目中使用反应版本16.9.0。因为你的 UI 工具包对 React 16.9.0 有对等依赖
  • 您也可以重新发布您的 UI 套件包,因为反应版本指定为 ^16.9.0,这可能会将 UI 套件反应版本更新到 16.10.2。

标签: javascript reactjs webpack


【解决方案1】:

查看 webpack 配置,我可以看到 UI 工具包与 react 捆绑在一起,这可能会导致问题。

为避免这种情况,您可以使用 webpack 外部组件。

https://webpack.js.org/configuration/externals/

externals 配置选项提供了一种排除方式 来自输出包的依赖项。相反,创建的包 依赖于存在于消费者环境中的依赖关系。 此功能通常对库开发人员最有用,但是 它有多种应用。

因此您可以更新 UI Kit webpack 配置以不包含 react,并且 peerDependencies 应该负责处理该库的任何使用者的依赖关系。

更新了 webpack.config

const path = require("path");
module.exports = {
  mode: "production",
  entry: "./src/index.js",
  output: {
    path: path.resolve("dist"),
    filename: "index.js",
    libraryTarget: "commonjs2"
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /(node_modules)/,
        use: "babel-loader"
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2|otf)$/,
        use: [
          {
            loader: "file-loader",
            options: {
              name: "[name].[ext]",
              limit: 10000,
              mimetype: "application/font-woff"
            }
          }
        ]
      }
    ]
  },
  resolve: {
    alias: {
      components: path.resolve(__dirname, "src/components/"),
      utils: path.resolve(__dirname, "src/utils/"),
      themes: path.resolve(__dirname, "src/themes/")
    },
    extensions: [".js", ".jsx"]
  },
  externals: {
        // Use external version of React
        react: "react"
 },
  devtool: false
};

我已经发布了一个测试包来确认这一点 (react-ui-kit-dontuse)。

演示链接

v0.0.21(Without webpack externals) 

https://stackblitz.com/edit/react-xyjgep

v0.0.23(With webpack externals) 

https://stackblitz.com/edit/react-ihnmrl

测试包源码:https://github.com/nithinthampi/react-ui-lib-test

希望这会有所帮助!

【讨论】:

  • 不客气!!!如果这有帮助,请标记为正确答案/赞成:)
猜你喜欢
  • 2022-07-26
  • 2021-06-04
  • 2019-10-08
  • 2018-10-25
  • 1970-01-01
  • 2021-07-06
  • 2023-02-08
  • 2017-04-15
  • 1970-01-01
相关资源
最近更新 更多