不能在我的 React 组件库中使用 Hooks。不变违规:无效的钩子调用

Uri*_*ami 10 reactjs webpack babeljs react-hooks

过去几周我一直在尝试创建我自己的组件库,一切都很顺利,除了我无法让钩子工作。每当我从库中导入一个使用钩子的组件时,我都会得到“钩子只能在函数组件的主体内调用”。

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

我希望这是 React 被复制的事情,我在运行时看不到npm ls react

这是我的 webpack.config.js

const path = require('path');
var nodeExternals = require('webpack-node-externals');
module.exports = {
	entry: './src/index.js',
	module: {
		rules: [
			{
				test: /\.js$/,
				exclude: /node_modules/,
				use: {
					loader: 'babel-loader',
				}
			},
			{
				test: /\.scss$/,
				sideEffects: true,
				use: [
					{ loader: 'style-loader' },
					{ loader: 'css-loader' },
					{ loader: 'sass-loader' },
				],
			},
			{
				test: /\.(png|gif|jpg|svg)$/,
				use: {
					loader: 'url-loader',
					options: {
						limit: 50000,
					},
				},
			},
			{
				test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
				use: [
				{
					loader: 'file-loader',
					options: {
					name: '[name].[ext]',
					outputPath: 'fonts/'
					}
				}
				]
			}
		],
	},
	resolve: {
		extensions: ['.scss', '.ttf', '.js', '.json', '.png', '.gif', '.jpg', '.svg'],
		},
	output: {
		path: path.resolve(__dirname, 'dist/'),
		publicPath: '',
	filename: 'index.js',
		libraryTarget: 'umd',
	},
	target: 'node',
  	externals: [ nodeExternals() ]
};
Run Code Online (Sandbox Code Playgroud)

这是我的包-json

{
  "name": "ui-components",
  "version": "1.1.1",
  "description": "componentes UI",
  "main": "dist/index.js",
  "scripts": {
    "test": "jest",
    "build": "webpack --mode production",
    "storybook": "start-storybook -p 9001",
    "docz:dev": "docz dev",
    "docz:build": "docz build"
  },
  "repository": {
    "type": "git",
    "url": "..."
  },
  "keywords": [
    "react",
    "shared",
    "components",
    "botbit"
  ],
  "author": "Uriel Chami",
  "license": "MIT",
  "devDependencies": {
    "@babel/core": "^7.2.2",
    "@babel/preset-env": "^7.2.3",
    "@babel/preset-react": "^7.0.0",
    "@storybook/addon-actions": "^5.0.0",
    "@storybook/addon-storyshots": "^5.1.10",
    "@storybook/react": "^5.0.0",
    "@tulipjs/eslint-config": "^1.1.1",
    "babel-loader": "^8.0.1",
    "babel-plugin-macros": "^2.6.1",
    "css-loader": "^1.0.0",
    "docz": "^1.2.0",
    "docz-theme-default": "^1.2.0",
    "file-loader": "^4.1.0",
    "jest": "^24.8.0",
    "node-sass": "^4.9.3",
    "react": "^16.9.0",
    "react-dom": "^16.9.0",
    "react-router-dom": "^5.0.1",
    "react-test-renderer": "^16.8.6",
    "sass-loader": "^7.1.0",
    "style-loader": "^0.23.1",
    "url-loader": "^1.1.2",
    "webpack": "^4.28.3",
    "webpack-cli": "^3.2.0",
    "webpack-node-externals": "^1.7.2"
  },
  "peerDependencies": {
    "react": "16.9.0",
    "react-dom": "16.9.0"
  },
  "dependencies": {
    "mdbreact": "..."
  }
}
Run Code Online (Sandbox Code Playgroud)

npm link用来测试库的功能,但我也可以将它部署到 GitHub 和npm update它。

我添加window.React1 = require('react');了 node_modules/react-dom/index.js(在使用我的库的应用程序中)。和

  require('react-dom');
  window.React2 = require('react');
  console.log(window.React1);
  console.log(window.React1 === window.React2);
Run Code Online (Sandbox Code Playgroud)

在我的 App.js(在使用我的库的应用程序中)。

它抛出true. 我慢慢变得无知了。有任何想法吗?


编辑:

我尝试使用 Hooks 的代码是:

import React, {useEffect} from 'react';

export const Test = () => {
    useEffect(()=>{
        console.log("component did mount");
    } , [])
    return(<div>Hola!</div>);
}
Run Code Online (Sandbox Code Playgroud)

编辑 2

当我构建yarn webpack --mode development它时会抛出'require is not defined'

如果有人想玩弄,这里有一个包含我完整代码的 GitHub 存储库:https : //github.com/uchami/hooks-not-working


编辑 3

我添加了组件库(ui-components)yarn add git+ssh:repository。我导入库的应用程序只是一个简单的 create-react-app。

我只是实现了Test组件(这是使用 Hooks的组件) usingimport {Test} from 'ui-components'并且我就像那样使用它<Test></Test>

ui-components项目的编译就yarn build在控制台上。在后台正在做的是调用yarn webpack --mode production. 如果你打电话,yarn webpack --mode development你会看到额外的详细错误输出。

for*_*d04 15

“只能在函数组件的主体内部调用钩子。”

让我们根据React 文档排除所有可能性:

  1. 你可能有不匹配的 React 和 React DOM 版本。

  2. 你可能违反了Hooks 规则

  3. 您可能在同一个应用程序中拥有多个 React 副本。

1.) 如果不确定,请尝试在您的应用程序中重新安装reactreact-dom使用最新版本,以便它们 100% 匹配(或查看您的package-lock.json/ 纱线锁):

npm i react@latest react-dom@latest
Run Code Online (Sandbox Code Playgroud)

2.) 你的useEffectHook 在里面的用法Test看起来不错 -Test是一个函数组件useEffect顶层调用。

3.) 这将是我对手头错误的主要猜测。

您正在使用npm link链接库进行本地测试。npm linknode_modules在应用程序项目的node_modules. react 安装既作为devDependencies在图书馆和dependencies在应用程序项目。

现在,当 Webpack 捆绑应用程序项目时,它会react从库或应用程序中进行选择——以包含在node_modules相对于导入模块最近的文件夹中的为准。

解决方案

Invalid Hook Call Warning页面上提到了一个修复:

假设myappmylib是同级文件夹,一种可能的解决方法是npm link ../myapp/node_modules/reactmylib. 这应该使库使用应用程序的 React 副本。

替代方案:告诉 Webpack 始终解析为单个react包 - 应用程序中的包node_modules(归功于两个问题)。webpack.config.js

resolve: {
  ...
  alias: {
    // Needed when library is linked via `npm link` to app
    react: path.resolve("./node_modules/react")
  }
}
Run Code Online (Sandbox Code Playgroud)

“要求未定义”

当您运行由错误的 Webpack 配置捆绑的 Web 应用程序时,可能会发生这种情况,其中require调用不会被删除并被实际代码模块替换。

如果应用程序项目基于create-react-app,您可以在 app 中导入库并运行startbuild。给定自定义 Webpack 配置(例如 via eject),使用target:web(或省略target)运行构建并省略externals: [ nodeExternals() ].

  • “你说,你 npm 链接你的库进行本地测试。npm link 将为完整的库工作目录(包括“node_modules”)添加符号链接”这是整个提示中最有帮助的,但所有答案似乎都非常合理,我一直在尝试所有这些解决方案。感谢您的关注和反馈 (2认同)