npm 模块上的钩子调用无效



首先链接到存储库:https://github.com/vmarchesin/react-konami-code

您应该能够构建它(确保取消注释导出src/index.js(并链接到您的项目。也可以使用npm i -S react-konami-code@2.0.0-beta.0尝试并获取钩子的错误。我从2.0.0-beta.1上取下了钩子,因为它坏了。

问题描述

我为我的 npm 模块创建了一个自定义钩子,它在发布或将其用作模块后不起作用。我怀疑问题出在 webpack 如何捆绑它,但我无法解决它。

采取的步骤

  • 我确保在我的 webpack 配置中将reactreact-dom声明为外部。
externals: [
{
react: {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react',
},
'react-dom': {
root: 'ReactDOM',
commonjs2: 'react-dom',
commonjs: 'react-dom',
amd: 'react-dom',
},
},
],
  • package.json中宣布reactreact-dompeerDependencies
"peerDependencies": {
"react": "^16.13.1",
"react-dom": "^16.13.1"
},
  • 钩子正在工作。如果我声明并使用它,它就会起作用。如果我从模块导入它(或使用 npm 链接(,它不会。这是钩子的代码:
import { useEffect, useState, useCallback } from 'react';
export default (action, {
code = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65],
} = {}) => {
const [input, setInput] = useState([]);
const onKeyUp = useCallback(
(e) => {
const newInput = input;
newInput.push(e.keyCode);
newInput.splice(-code.length - 1, input.length - code.length);
setInput(newInput);
if (newInput.join('').includes(code.join(''))) {
action();
}
},
[input, setInput, code, action],
);
useEffect(() => {
document.addEventListener('keyup', onKeyUp);
return () => {
document.removeEventListener('keyup', onKeyUp);
};
}, [onKeyUp]);
};
  • 我不是在类组件中调用钩子。

我正在使用webpack@4.43.0以及babel@7babel-loader@8.1.0

以下是我导出 webpack 构建的索引文件的方法:

import Konami from './Konami';
export default Konami; // disregard this, it works
export { default as useKonami } from './useKonami'; // this doesn't work

以下是错误的屏幕截图和脚本:

未处理的运行时错误错误:无效的挂钩调用。钩子只能是 在函数组件的主体内部调用。这可能会发生 出于以下原因之一:

  1. 你可能有不匹配的 React 和渲染器版本(例如 React DOM(
  2. 你可能违反了钩子的规则
  3. 您可能在同一应用程序中有多个 React 副本

我遇到了同样的问题,尝试了所有解决方案,但没有一个奏效。

对此的解决方案是,我们需要将Webpack配置为基本上忽略 React 作为生产捆绑包的一部分以及对等依赖关系。

为此,请在webpack.config.js中添加以下行:

externals: {
"react": "commonjs react",
"react-dom": "commonjs react-dom",
}

我在尝试从我构建的 npm 包导入反应组件时遇到了相同的错误消息。正如错误消息的解释所暗示的那样,这可能是重复 React 的情况。

关于错误消息的重要部分是将reactreact-dom捆绑为外部导入,以便使用父项目的 react 而不是使用第二个重复的 React

我通过使用 rollup.js 构建我的 npm 包来解决这个问题,基本上遵循本指南。

我生成的 rollup.config.js:

import pkg from './package.json'
import babel from '@rollup/plugin-babel';
export default {
input: 'src/index.js',
output: [
{
file: pkg.main,
format: 'cjs',
exports: 'named',
sourcemap: true,
strict: false
}
],
plugins: [babel({ babelHelpers: 'bundled' })],
external: ['react', 'react-dom']
}

在你的 npm 包中需要以下开发依赖项(假设你还必须使用 babel 进行转译(:

npm i -D rollup babel-core @rollup/plugin-babel

您可以像这样捆绑汇总:

// add that to your package.json
"scripts": {
"build": "rollup -c",
"start": "rollup -c -w"  // for watching changes
},

有了npm link,甚至可以在父项目中为您正在开发的打包的 react 组件进行热重载,而无需任何 npm 发布。耶。

我在这里看到两个问题,可能会导致您在控制台上看到的错误:

  1. 不导入React所以违反了钩子的规则 - 只从 React 函数调用钩子。
  2. 问题也可能来自您这里没有命名组件。

因此,我将React包括以下内容:

import React, { useEffect, useState, useCallback } from 'react';

您也可以尝试将其导出为以下内容:

export default function ComponentName (action, {
code = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65],
} = {}) {
// your component code
}

或者,如果您仍想使用箭头功能,则:

const ComponentName = (action, {
code = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65],
} = {}) => {
// your component code
}
export default ComponentName;

你可以参考这篇文章:
不要使用匿名函数来构造 React 功能组件

我希望这有帮助!

相关内容

  • 没有找到相关文章

最新更新