无法在我的React Component Library中使用Hooks。永久违反:无效的挂钩调用

时间:2019-08-12 02:57:49

标签: reactjs webpack babel 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() ]
};

这是我的package-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": "..."
  }
}

我正在使用npm link来测试库的功能,但是我也可以将其部署到GitHub上并npm update进行部署。

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

  require('react-dom');
  window.React2 = require('react');
  console.log(window.React1);
  console.log(window.React1 === window.React2);

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

它抛出true。我慢慢变得一无所知。有什么想法吗?


编辑:

我尝试使用Hooks的代码是:

import React, {useEffect} from 'react';

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

编辑2

当我构建yarn webpack --mode development时,它抛出'require not defined'(未定义需求)

如果有人想开玩笑,这里是我完整代码的GitHub存储库:https://github.com/uchami/hooks-not-working


编辑3

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

我只是使用Test实现import {Test} from 'ui-components'组件(使用Hooks的组件),就象<Test></Test>一样使用它。

ui-components项目的编译只是控制台上的yarn build。在后台执行的操作是调用yarn webpack --mode production。如果您致电yarn webpack --mode development,将会看到额外的详细错误输出。

4 个答案:

答案 0 :(得分:2)

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

让我们根据link排除所有可能性。

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

  2.   
  3. 您可能正在违反挂钩规则。

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

  6.   

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

npm i react@latest react-dom@latest

2。)您在测试组件中的useEffect钩看起来不错。

3。)如果必须选择,这将是我的主要猜测。

您说过,您npm link在本地测试库中。 npm link将为应用程序项目的“ node_modules”内的完整库工作目录(包括“ node_modules”)添加符号链接。您已经在library中将react作为devDependencies以及在您的应用程序项目中作为依赖项安装了(顺便说一句,您可以从库中删除react-dom,仅将组件作为API提供)。您的应用程序项目,它将选择在库中还是在应用程序中做出反应-相对于导入模块而言,包含在最近的node_modules文件夹中。

在同一hook warning page上提到了一个修复程序:

  

假设myapp和mylib是同级文件夹,一种可能的解决方法是从mylib运行npm链接../myapp/node_modules/react。这应该使库使用应用程序的React副本。

替代方法:告诉Webpack始终只解析一个反应包(您的应用程序node_modules中的一个)。 webpack.config.js:

resolve: {
  ...
  alias: {
    // Needed when you are link your library via `npm link` to the app.
    // react-dom should be only installed in app.
    react: path.resolve("./node_modules/react")
  }
}

贷方转到these issues

“未定义要求”

当您运行的Web应用程序被错误的Webpack配置捆绑在一起时,可能会发生这种情况,在该应用程序中,要求调用不会被丢弃,并由实际的代码模块代替。

如果您的应用程序项目基于create-react-app,则只需将您的库导入应用程序中并执行startbuild。如果您为应用程序使用自定义Webpack配置(例如,退出cra设置),请使用target:web(或忽略目标)运行构建,并忽略externals: [ nodeExternals() ]-看一下{{3} }。

答案 1 :(得分:1)

仅仅是您要在运行与钩子不兼容的旧版React的React应用中使用您的库吗?

我刚刚创建了一个新的create-react-app,将您的存储库添加为yarn add https://github.com/uchami/hooks-not-working的依赖项,并且毫无疑问将Test组件添加到默认的App.js

回滚我应用的React版本后,我才得到一个错误。

答案 2 :(得分:1)

这可能也有帮助: React hooks duplicate react package

我遇到了同样的问题,但更糟糕的是,我必须使用自己的库来管理多个应用程序。

提出的解决方案可以解决所有“多个反应库”错误

答案 3 :(得分:0)

您是否尝试过将目标从node更改为web?这可能会导致一些问题。

也不知道计划使用库的所有详细信息,但是当您在已经具有可处理构建步骤的环境中使用库时,babel ./src --out-dir ./core --copy-files这样的简单操作可能会很有用捆绑。

我要添加评论,但嗯。