npm模块上的无效钩子调用

时间:2020-05-12 10:39:30

标签: reactjs npm webpack react-hooks babeljs

首先链接到仓库: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',
    },
  },
],
  • react中将react-dompeerDependencies声明为package.json
"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

以下是该错误的screenshot和成绩单:

未处理的运行时错误 错误:无效的挂钩调用。挂钩只能在功能组件的主体内部调用。可能由于以下原因之一而发生: 1.您的React和渲染器版本可能不匹配(例如React DOM) 2.您可能违反了《钩子规则》 3.您可能在同一应用程序中拥有多个React副本

3 个答案:

答案 0 :(得分:1)

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

关于错误信息的重要部分是将 DocumentApp.getActiveDocument().getBody().clear() document2 = DocumentApp.openById("Document_ID").getBody().getText() DocumentApp.getActiveDocument().getBody().appendParagraph(document2) react 捆绑为外部导入,以便父项目的反应正在使用,而不是使用第二个,这是一个重复的 React

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

我得到的 rollup.config.js:

react-dom

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

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 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 }, 甚至可以在父项目中为您正在开发的打包 React 组件进行热重载,而无需任何 npm 发布。耶。

答案 1 :(得分:0)

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

  1. 不导入React会破坏Rules of Hooks-Only Call Hooks from React Functions
  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;

您可以参考这篇文章:
Do not use anonymous functions to construct React functional components

我希望这会有所帮助!

答案 2 :(得分:0)

我遇到了相同的问题,尝试了所有解决方案,但没有成功。 我们需要配置Webpack使其基本上忽略React作为生产捆绑包的一部分以及对等依赖项.so plz在webpack.config.js中添加以下行 n=100000