React + Antd + Rollup 组件库“错误:钩子调用无效.钩子只能在函数组件的主体内部调用" [英] React + Antd + Rollup Component Library "Error: Invalid hook call. Hooks can only be called inside of the body of a function component"

查看:94
本文介绍了React + Antd + Rollup 组件库“错误:钩子调用无效.钩子只能在函数组件的主体内部调用"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在构建一个 UI 库,以简化跨多个应用程序的维护.这些目前使用 Ant Design.

I'm currently building a UI library to simplify maintenance across multiple applications. These currently use Ant Design.

一切似乎都很顺利...我在 package.jsonrollup.config.js(通过外部)中添加了我的对等依赖项,我能够获取 Rollup 以生成 es 和 cjs 二进制文件,该二进制文件成功导出只是我的代码.

All seemed to go fine... I added my peer dependencies in both package.json and rollup.config.js (via externals) and I was able to get Rollup to produce an es and cjs binary which successfully exports just my code.

但是,当我将其中任何一个导入到我的主机应用程序(Electron 和/或 React,已经使用 antd 没有问题)时,我收到以下错误:

However, when I import either of these into my host application (Electron and/or React, already using antd without issue) I am receiving the following error:

Uncaught 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.
    at resolveDispatcher (react.development.js:1476)
    at Object.useContext (react.development.js:1484)
    at Button (button.js:129)
    at renderWithHooks (react-dom.development.js:14985)
    at updateForwardRef (react-dom.development.js:17044)
    at beginWork (react-dom.development.js:19098)
    at HTMLUnknownElement.callCallback (react-dom.development.js:3945)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994)
    at invokeGuardedCallback (react-dom.development.js:4056)
    at beginWork$1 (react-dom.development.js:23964)
resolveDispatcher @ react.development.js:1476
useContext @ react.development.js:1484
Button @ button.js:129
renderWithHooks @ react-dom.development.js:14985
updateForwardRef @ react-dom.development.js:17044
beginWork @ react-dom.development.js:19098
callCallback @ react-dom.development.js:3945
invokeGuardedCallbackDev @ react-dom.development.js:3994
invokeGuardedCallback @ react-dom.development.js:4056
beginWork$1 @ react-dom.development.js:23964
performUnitOfWork @ react-dom.development.js:22779
workLoopSync @ react-dom.development.js:22707
renderRootSync @ react-dom.development.js:22670
performSyncWorkOnRoot @ react-dom.development.js:22293
scheduleUpdateOnFiber @ react-dom.development.js:21881
updateContainer @ react-dom.development.js:25482
(anonymous) @ react-dom.development.js:26021
unbatchedUpdates @ react-dom.development.js:22431
legacyRenderSubtreeIntoContainer @ react-dom.development.js:26020
render @ react-dom.development.js:26103
(anonymous) @ renderer.tsx:129
./src-template/renderer.tsx @ renderer.tsx:150
__webpack_require__ @ bootstrap:789
fn @ bootstrap:100
0 @ renderer.tsx:150
__webpack_require__ @ bootstrap:789
(anonymous) @ bootstrap:856
(anonymous) @ bootstrap:856
react-dom.development.js:20085 The above error occurred in the <Button> component:

    at Button (http://localhost:3000/main_window/index.js:48908:30)
    at ../../ui-library/dist/index.cjs.js.exports.ComponentA (http://localhost:3000/main_window/index.js:101188:13)
    at div
    at App (http://localhost:3000/main_window/index.js:204727:30)

我无法理解如何继续...我已经尝试调整我的汇总配置(如下)并将我的所有代码剥离到只有一个测试器组件(antd Button),但我仍然遇到错误.

I cannot understand how to proceed... I've tried to tweak my rollup config (below) and strip out all my code down to just a single tester component (antd Button) yet I still experience the error.

当我 console.log() 导入对象时,我可以看到 es 和 cjs 二进制文件都公开了测试器组件,但存在错误.

When I console.log() the import object I can see that both the es and cjs binaries exposes the tester component but the error is present.

我在这里遗漏了什么?

  • 反应
  • 响应DOM
  • 蚂蚁
  • @ant-design/icons
import { DEFAULT_EXTENSIONS } from '@babel/core'
import babel from '@rollup/plugin-babel'
import typescript from 'rollup-plugin-typescript2'
import commonjs from '@rollup/plugin-commonjs'
import external from 'rollup-plugin-peer-deps-external'
import postcss from 'rollup-plugin-postcss'
import resolve from '@rollup/plugin-node-resolve'
import url from '@rollup/plugin-url'
import svgr from '@svgr/rollup'
import { terser } from 'rollup-plugin-terser'

import pkg from './package.json'


const isDevelopment = process.env.NODE_ENV === 'development' ? true : false;

console.log('EXPECTED EXTERNALS', [
      ...Object.keys(pkg.dependencies || {}),
      ...Object.keys(pkg.peerDependencies || {})
])
export default {
  input: 'src/index.jsx',
  output: [
    {
      file: `dist/index.es.js`,
      format: 'esm',
      exports: 'named',
      sourcemap: isDevelopment,
    },
    {
      file: `dist/index.cjs.js`,
      format: 'cjs',
      exports: 'named',
      sourcemap: isDevelopment,
    }
  ],
  context: 'this',
  external: [
        ...Object.keys(pkg.dependencies || {}),
        ...Object.keys(pkg.peerDependencies || {})
  ],
  plugins: [
    external(),
    typescript({
      rollupCommonJSResolveHack: true,
      clean: true,
      tsconfig: './tsconfig.json',
    }),
    babel({
      presets: [
        'react-app',
      ],
      extensions: [
        ...DEFAULT_EXTENSIONS,
        '.ts',
        '.tsx',
      ],
      plugins: [
        ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }],
        "@babel/plugin-proposal-object-rest-spread",
        "@babel/plugin-proposal-optional-chaining",
        "@babel/plugin-syntax-dynamic-import",
        "@babel/plugin-proposal-class-properties",
        "transform-react-remove-prop-types"
      ],
      babelHelpers: 'runtime',
    }),
    postcss({
        extensions: ['.css', '.scss', '.less'],
        use: ['sass', ['less', {
          lessOptions: {
             javascriptEnabled: true
          }
        }]],
    }),
    svgr(),
    url(),
    resolve(),
    commonjs(),
    terser({ mangle: true }),
  ],
}

Package.json(组件库)

{
  "name": "ui-library",
  "version": "0.0.1",
  "description": "UI library components",
  "main": "index.js",
  "scripts": {
    "build": "rm -rf dist && mkdir dist && NODE_ENV=production BABEL_ENV=production rollup -c"
  },
  "peerDependencies": {
    "@ant-design/icons": "^4.3.0",
    "antd": "^4.9.2",
    "react": "^17.0.1",
    "react-dom": "^17.0.1"
  },
  "devDependencies": {
    "@babel/core": "^7.12.10",
    "@babel/plugin-proposal-class-properties": "^7.12.1",
    "@babel/plugin-proposal-object-rest-spread": "^7.12.1",
    "@babel/plugin-proposal-optional-chaining": "^7.12.7",
    "@babel/plugin-syntax-dynamic-import": "^7.8.3",
    "@babel/plugin-transform-react-jsx": "^7.12.10",
    "@babel/preset-env": "^7.12.10",
    "@babel/preset-react": "^7.12.10",
    "@babel/preset-typescript": "^7.12.7",
    "@rollup/plugin-babel": "^5.2.2",
    "@rollup/plugin-commonjs": "^17.0.0",
    "@rollup/plugin-node-resolve": "^11.0.0",
    "@rollup/plugin-typescript": "^8.0.0",
    "@rollup/plugin-url": "^6.0.0",
    "@svgr/rollup": "^5.5.0",
    "@types/node": "^14.14.11",
    "@types/react": "^17.0.0",
    "@types/react-dom": "^17.0.0",
    "@typescript-eslint/eslint-plugin": "^4.9.1",
    "@typescript-eslint/parser": "^4.9.1",
    "babel-loader": "^8.2.2",
    "babel-plugin-import": "^1.13.3",
    "babel-plugin-transform-react-remove-prop-types": "^0.4.24",
    "babel-preset-react-app": "^10.0.0",
    "css-loader": "^4.2.1",
    "eslint": "^7.15.0",
    "eslint-config-airbnb-typescript": "^12.0.0",
    "eslint-plugin-react": "^7.21.5",
    "less-loader": "^7.1.0",
    "mini-css-extract-plugin": "^1.3.2",
    "react-is": "^17.0.1",
    "rollup": "^2.34.2",
    "rollup-plugin-peer-deps-external": "^2.2.4",
    "rollup-plugin-postcss": "^4.0.0",
    "rollup-plugin-terser": "^7.0.2",
    "rollup-plugin-typescript2": "^0.29.0",
    "sass-loader": "^10.1.0",
    "style-loader": "^2.0.0",
    "typescript": "^4.1.2",
    "url-loader": "^4.1.1"
  }
}

组件库测试器组件

import React from 'react';

import { Button, Radio } from 'antd';
import { DownloadOutlined } from '@ant-design/icons';
import { SizeType } from 'antd/lib/config-provider/SizeContext';


export interface ButtonProps {
  /**
   * What background color to use
   */
  backgroundColor?: string;
  /**
   * Button contents
   */
  label: string;

  /**
   * Size (small | large)
   */
  size: SizeType;
  /**
   * Optional click handler
   */
  onClick?: () => void;
}


// export const ComponentA = (props: ButtonProps) => (<button type="button" onClick={props.onClick} style={{ backgroundColor: props.backgroundColor}}>{ props.label }</button>);

export const ComponentA = (props: ButtonProps) => (
  <Button
    type="primary"
    shape="round"
    icon={<DownloadOutlined />}
    size={props.size || 'middle'}
    onClick={props.onClick || null}
  >
    {props.label || ''}
  </Button>
)

更新:添加 rollup-plugin-visualizer 输出

推荐答案

如果在您在主项目中链接库的本地版本以加快开发速度时发生此问题.可能与React 版本重复"有关.

If this issue happens while you're linking the local version of your library in your main project to speed up the development. It might be related to "duplicate version of React".

https://reactjs.org/warnings/invalid-hook-call-警告.html

当您使用 npm link 或等效物时,也会出现此问题.在这种情况下,你的打包器可能会看到"两个 Reacts——一个在应用程序文件夹中,一个在你的库文件夹中.假设 myapp 和 mylib 是同级文件夹,一种可能的解决方法是从 mylib 运行 npm link ../myapp/node_modules/react.这应该使库使用应用程序的 React 副本.

This problem can also come up when you use npm link or an equivalent. In that case, your bundler might "see" two Reacts — one in application folder and one in your library folder. Assuming myapp and mylib are sibling folders, one possible fix is to run npm link ../myapp/node_modules/react from mylib. This should make the library use the application’s React copy.

简而言之:

  • 在/your-app/node_modules/react 中运行 npm link.这应该是 React 的全局链接.
  • 在/your-ui-library 中运行 npm link react.这应该使库使用应用程序的 React 副本.
  • run npm link in /your-app/node_modules/react. This should make the React's global link.
  • run npm link react in /your-ui-library. This should make the library use the application’s React copy.

这篇关于React + Antd + Rollup 组件库“错误:钩子调用无效.钩子只能在函数组件的主体内部调用"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆