反应库中的反应钩子给出无效的钩子调用错误

Posted

技术标签:

【中文标题】反应库中的反应钩子给出无效的钩子调用错误【英文标题】:React hooks in react library giving Invalid hook call error 【发布时间】:2019-09-25 00:41:19 【问题描述】:

我使用https://www.npmjs.com/package/create-react-library 创建了一个反应库 并成功将其用于其他 React 项目。 但是当我尝试在库中使用 react hooks 功能时,它给了我以下错误。

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
.....

我的图书馆 我只是尝试在我的组件中使用 useState,如下所示。

import React,  useState  from 'react'

const General = (props) => 

    const [count, setCount] = useState(0);
    return (
        <div>
           General component
        </div>
    )


export default General

我正在使用 "react": "^16.8.6""react-dom": "^16.8.6"

我的 React 应用程序 使用https://github.com/facebook/create-react-app 创建了一个应用程序,并使用上面的库如下。

import Reactfrom 'react'
import  General  from 'my.lib'
const accountSummary = props => 

  return (
    <div>
      <General>
    </div>
  )


export default accountSummary

两者都有相同的 react 版本,并且库使用了与 peerDependencies 相同的 react-dom 和 react 版本

【问题讨论】:

有一点是肯定的,你没有违反 Hooks 的规则。 你使用的是什么版本的 React 和 React DOM? 问题在于我在本地运行库,并在 py package.json 中使用“my.library”:“file:../my.library”引用它。 Lib 在另一个反应实例中单独运行。如果我将它发布为 npm 库并使用它就可以正常工作。 这就是你打破规则的方式......你在一个组件(MyLibrary)中使用了一个钩子(比如 useState),它由你的 Rollup 捆绑到 dist/index.js (其中默认情况下由 create-react-library 配置)。当捆绑发生时你的钩子可能会被推到一个条件(比如说如果)并且规则被打破了! @YugandharPathi 如果是这样,解决方案是什么?我想我可能有同样的问题。 React 不能脆弱到无法处理捆绑,不是吗? 【参考方案1】:

我用create-react-library 创建了一个React 库,这个库是你的General 组件。我已将它发布到 npm https://www.npmjs.com/package/***-test 和一个 React 应用程序以供在此处使用它 https://codesandbox.io/s/mm7yl83o28。

只需点击General component文字,count就会增加。

我无法重现您的问题,请使用此测试来检查您的实现。

【讨论】:

我终于找到了问题所在。我在我的 react 应用程序中安装了“react-scripts”,它现在可以正常工作了。 很好,所以丢失了数据包 问题在于我在本地运行库并使用“my.library”:“file:../my.library”引用它。 Lib 在另一个反应实例中单独运行。如果我将它发布为 npm 库并使用它就可以正常工作。 你是否在 ***-test 中使用了组件内部的钩子(比如 )? @YugandharPathi 是的【参考方案2】:

我在我的应用程序中包含了我的组件库(任何库),就像@Janith 使用my-comp-lib:"file:../.." 所做的那样(我不想在每次我想测试时都发布)并且我遇到了同样的问题。

无效的挂钩调用。 Hooks 只能在 a 的主体内部调用 功能组件。这可能发生在以下情况之一 原因:

    您可能有不匹配的 React 版本和渲染器(例如 React DOM) 您可能违反了 Hooks 规则 您可能在同一个应用中拥有多个 React 副本,请参阅 react-invalid-hook-call 以了解有关如何调试和

解决这个问题

我可以通过使我的应用程序和库指向相同的反应(包)位置来解决此问题。

Below are the steps I followed :
1. In Your Application:
a) cd node_modules/react && npm link
b) cd node_modules/react-dom && npm link

2. In Your Library
a) npm link react
b) npm link react-dom

3)Stop your dev-server and do `npm start` again.

有效!!

更多详情请参考以下链接..

https://github.com/facebook/react/issues/14721

https://github.com/facebook/react/pull/14690

https://github.com/facebook/react/issues/13991

注意:如果您将包发布到工件并安装,则不会发生此问题,因为您将 react 和 react-dom 作为对等依赖项,并且它们不会包含在分发中。因此,您的包和应用程序使用安装在应用程序中的相同反应。

【讨论】:

库中需要安装react-dom吗?它没有显式导入到 OP 编写的库代码中。 顺便说一句,更简洁的解决方案是从库文件夹运行此命令:“npm link ../web-application/node_modules/react”。这是假设库和 Web 应用程序位于同级文件夹中。如果库还需要使用 react-dom,可以使用类似的命令。 @yugandhar-pathi 非常感谢这个解决方案! 感谢您的回答。真的很有帮助 感谢您的解决方案@yugandhar-pathi!但是有一个问题:我们没有将我们的包发布到 npm 中!我们将它放在我们的 gitlab 服务器上,然后使用 gitlab 部署令牌将其安装在其他应用程序上。我们如何在生产中处理这个问题?我们不能在生产中使用npm link【参考方案3】:

我刚刚遇到了同样的问题。我可以通过在我的示例应用程序中指向与我的库中相同的反应来修复它:

应用结构

示例 package.json src(库) package.json

因此,从示例 > package.json 我将 react 更改为:

    "react": "link:../node_modules/react",

这很像上面列出的npm link,但它不会在您每次 npm 安装时消失。

【讨论】:

是的,这是我摆脱上述问题的解决方案。 请注意,较新版本的 npm 已弃用链接。相反,您需要使用文件:"react": "file:../node_modules/react"【参考方案4】:

也许这会有所帮助:

Link - how to create react component npm package with example

【讨论】:

欢迎提供解决方案链接,但请确保您的答案在没有它的情况下有用:add context around the link 这样您的其他用户就会知道它是什么以及为什么会出现,然后引用最相关的您链接到的页面的一部分,以防目标页面不可用。 Answers that are little more than a link may be deleted. 这解决了我的问题。我使用 npm link 在本地测试一个包,这意味着我有重复的 React 版本。 非常好的解决方案。 谢谢。这帮助很大!【参考方案5】:

除了链接 react 和 react-dom 之外,当我将应用程序到库的链接更改为“link:../”而不是“file:../”时,它对我有用。

【讨论】:

我得到一个错误“不支持的 URL 类型“链接:”:当我尝试这个时。我在 npm 6.4.1【参考方案6】:

添加到您的组件库的package.json

"peerDependencies": 
  "react": "<your version>"

这样您的 lib 包将使用与您的主应用程序相同的 react 包。 https://nodejs.org/es/blog/npm/peer-dependencies/

【讨论】:

【参考方案7】:

React 17 + React 测试库 + Umi(前端框架,内置 react-router)

就我而言,当我运行单元测试时,我收到一条错误消息“无效的挂钩调用”。

经过一段时间的尝试,我找到了两种解决方法。

    降级到 React 16.x,一切都会好起来的。 继续使用 React 17.x,并且 还是要写import React from 'react' 单独安装react-router-dom

我觉得可能是react-router的问题,但是由于我的理解有限,目前还没有更好的解决方案。

【讨论】:

【参考方案8】:

还要检查你的 npm 版本。我的版本是 7.0.8,已经过时了,改成 6.14.8 后一切正常!

【讨论】:

【参考方案9】:

在 REACT NATIVE 中使用真实应用进行测试时

我有同样的问题,我在我的自定义库中删除了我的 node_module 文件并修复了它..

安装直接模块时的问题

yarn add c:/user......./react-native-some-lib

【讨论】:

【参考方案10】:

我遇到了同样的问题,使用 rush monorepo,配置 ui-package 并使用 nextjs 构建应用程序。

解决方案是在package.json添加以下代码

"resolutions": 
  "react": "17.0.1", // verificate your react version
  "react-dom": "17.0.1"

在图书馆的package.json

"peerDependencies": 
   "react": "17.0.1",
   "react-dom": "17.0.1"
 ,

在此处查看更多信息:https://github.com/vercel/next.js/issues/9022#issuecomment-728688452

【讨论】:

以上是关于反应库中的反应钩子给出无效的钩子调用错误的主要内容,如果未能解决你的问题,请参考以下文章

块编辑器给出无效的钩子调用错误

反应钩子:无效的钩子调用

反应:无效的钩子调用。 Hooks 只能在函数组件的主体内部调用

无效的挂钩调用。钩子只能在反应函数组件内部使用...... useEffect,redux

为啥反应钩子使用状态显示错误消息

react-intl 与 react-testing-library 给出了无效的钩子调用错误