iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > node.js >如何解决第三方组件的Hooks报错问题
  • 289
分享到

如何解决第三方组件的Hooks报错问题

2024-04-02 19:04:59 289人浏览 泡泡鱼
摘要

这篇文章主要介绍“如何解决第三方组件的Hooks报错问题”,在日常操作中,相信很多人在如何解决第三方组件的Hooks报错问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何

这篇文章主要介绍“如何解决第三方组件的Hooks报错问题”,在日常操作中,相信很多人在如何解决第三方组件的Hooks报错问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何解决第三方组件的Hooks报错问题”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

事发

某个需求需要引入一个第三方组件库。

当引入组件库中的函数组件A后,React运行时报错:

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

从React文档了解到,这是由于「错误使用Hooks造成的」。

官网给出的可能的错误原因有3种:

1.React和ReactDOM版本不匹配

需要v16.8以上版本的ReactDOM才支持Hooks。

我们项目使用的是v17.0.2,不属于这个原因。

2.打破了Hooks的规则

Hooks只能在函数组件或自定义Hooks顶层调用。

翻看A组件源码,报错的是一个顶层调用的useRef:

function A() {   // ...   var xxxRef = useRef(null);   // ... }

不属于这个原因。

3.重复的React

载录自React文档:

  • 为了使 Hook 正常工作,你应用代码中的 react 依赖以及 react-dom 的 package 内部使用的 react  依赖,必须解析为同一个模块。

  • 如果这些 react 依赖解析为两个不同的导出对象,你就会看到本警告。这可能发生在你意外地引入了两个 react 的 package 副本。

读起来好绕,看起来这条的嫌疑最大。

定位问题

在报错的useRef中打上断点,发现其来自于:

Http://localhost:8081/Users/项目目录/node_modules/组件库/node_modules/react/cjs/react.development.js

在项目里其他调用Hooks但是未报错的地方打上断点,发现资源来自于:

http://localhost:8081/Users/项目目录/node_modules/react/cjs/react.development.js

报错的useRef和项目其他Hooks引用了不同的react.development.js。

翻看「组件库」的package.JSON,发现他将react与react-dom作为dependencies安装:

"dependencies": {   "react": "^16.13.1",   "@babel/runtime-corejs3": "^7.11.2",   "react-dom": "^16.13.1" },

这样会在「组件库」目录的node_modules下创建这两个依赖。

作为一个「组件库」,这么做显然是不合适的。

临时解决

最好的做法是将这两个依赖作为peerDependencies,即将其作为外部依赖。

这样,当我们引入「组件库」时,「组件库」会使用我们项目中的react与react-dom,而不是自己安装一份。

但是我没有这个「组件库」的权限,只能在自己项目中做文章。

在package.json文档中提供了一个配置项:resolutions,可以临时解决这个问题。

resolutions允许你复写一个在项目node_modules中被嵌套引用的包的版本。

在我们项目的package.json中作出如下修改:

// 项目package.json {   // ...   "resolutions": {     "react": "17.0.2",     "react-dom": "17.0.2"   },   // ... }

这样,项目中用到的这两个依赖都会使用resolutions中指定的版本。

不管是「组件库」还是我们的项目代码中的react与react-dom,都会指向同一个文件。

现在问题是临时解决了,但是造成问题的原因是什么?

让我们深入Hooks源码内部来寻找答案。

深入源码

首先让我们思考2个问题:

当我们在一个Hooks内部调用其他Hooks时会报开篇提到的错误。

比如如下代码就会报错:

function App() {    useEffect(() => {     const a = useRef();   }, [])    // ... }

Hooks只是函数,他如何感知到自己在另一个Hooks内部执行?

就如上例子,useRef如何感知到自己在useEffect的回调函数中执行?

再看另一个问题,我们知道classComponent有componentDidMount与componentDidUpdate两个生命周期函数区分mount时与update时。

那么Hooks作为函数,怎么区分当前是mount时还是update时?

显然,Hooks源码内部存在一种机制,能够感知当前执行的上下文环境。

渐入佳境

在浏览器环境,我们会引用react与reactDOM两个包。

其中,在react包的代码中存在一个变量ReactCurrentDispatcher。

他的current参数指向当前正在使用的Hooks上下文:

var ReactCurrentDispatcher = {      current: null };

同时,在reactDOM中,在程序运行过程中,ReactCurrentDispatcher.current会根据当前上下文环境指向不同引用。

比如:

var HooksDispatcherOnMountInDEV = {   useState: function() { // ... },   useEffect: function() { // ... },   useRef: function() { // ... },   // ... } var HooksDispatcherOnUpdateInDEV = {   useState: function() { // ... },   useEffect: function() { // ... },   useRef: function() { // ... },   // ... } // ...

当处在DEV环境mount时,ReactCurrentDispatcher.current会指向HooksDispatcherOnMountInDEV。

当处在DEV环境update时,ReactCurrentDispatcher.current会指向HooksDispatcherOnUpdateInDEV。

再来看useRef的定义:

function useRef(initialValue) {   var dispatcher = resolveDispatcher();   return dispatcher.useRef(initialValue); }

内部调用的是dispatcher.useRef。

dispatcher即ReactCurrentDispatcher.current。

function resolveDispatcher() {   var dispatcher = ReactCurrentDispatcher.current;    if (!(dispatcher !== null)) {     {       throw Error( "Invalid hook call. ..." );     }   }    return dispatcher; }
  • 可以看到,开篇的错误正是由于dispatcher为null时抛出

这就是Hooks能区分mount与update的原因。

同理,DEV环境,当一个Hooks在执行时,ReactCurrentDispatcher.current会指向引用 ——  InvalidNestedHooksDispatcherOnUpdateInDEV。

在这种情况下再调用的Hooks,比如如下useRef:

var InvalidNestedHooksDispatcherOnUpdateInDEV = {   // ...   useRef: function (initialValue) {     currentHookNameInDev = 'useRef';     warnInvalidHookAccess();     updateHookTypesDev();     return updateRef();   },   // ... }

内部都会执行warnInvalidHookAccess报错,提示自己在别的Hooks内执行了。

真相大白

到这里我们终于知道开篇提到的问题发生的本质原因:

  • 由于「组件库」使用dependencies而不是peerDependencies,导致「组件库」中引用的react与reactDOM是「组件库」目录node_modules下的文件。

  • 项目中使用的react与reactDOM是项目目录node_modules下的文件。

  • 「组件库」中react与项目目录中react在运行时分别初始化ReactCurrentDispatcher

  • 这两个ReactCurrentDispatcher分别依赖对应目录的reactDOM

  • 我们在项目中执行项目目录下reactDOM的ReactDOM.render方法,他会随着程序运行改变项目目录中react包下的ReactCurrentDispatcher.current的指向

  • 「组件库」中的ReactCurrentDispatcher.current始终是null

  • 当调用「组件库」中的Hooks时,由于ReactCurrentDispatcher.current始终是null导致报错

到此,关于“如何解决第三方组件的Hooks报错问题”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: 如何解决第三方组件的Hooks报错问题

本文链接: https://www.lsjlt.com/news/83167.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何解决第三方组件的Hooks报错问题
    这篇文章主要介绍“如何解决第三方组件的Hooks报错问题”,在日常操作中,相信很多人在如何解决第三方组件的Hooks报错问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何...
    99+
    2024-04-02
  • vue第三方库中存在扩展运算符报错问题的解决方案
    目录vue第三方库中存在扩展运算符报错问题解决方案1、引入babel依赖2、在vue项目的src/.babelrc文件中(没有自己创建)下修改解决方法:vue第三方库中存在扩展运算符...
    99+
    2024-04-02
  • vue父组件调用子组件方法报错问题及解决
    目录vue父组件调用子组件方法报错vue父组件调用子组件方法及遇到的问题vue父组件调用子组件方法报错 在父组件定义了一个tab标签页,每一个标签页下面都调用不同的组件, 如下图所示...
    99+
    2024-04-02
  • 解决安装 Python 的第三方库 pandas 报错
    解决Python第三方库安装报错 在安装 Python 的第三方库 pandas 时,可能会遇到命令行报错 Command "python setup.py egg_info" failed with...
    99+
    2023-09-29
    python pandas numpy matplotlib
  • 怎么解决php com组件报错问题
    小编给大家分享一下怎么解决php com组件报错问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!php com组件报错的解决办法:1、在php.ini中修改配置...
    99+
    2023-06-08
  • 如何解决vue子组件修改父组件传来的props值报错问题
    这篇文章主要介绍如何解决vue子组件修改父组件传来的props值报错问题,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!vue不推荐直接在子组件中修改父组件传来的props的值,会报错...
    99+
    2024-04-02
  • win10第三方软件模糊如何解决
    使用第三方软件模糊的问题可能是由于高DPI缩放导致的。以下是一些解决方法: 调整DPI缩放设置:右键点击桌面空白处,选择“显示设置...
    99+
    2023-10-21
    win10
  • idle安装第三方库报错怎么解决
    在安装第三方库时出现报错,可能是由于网络问题、依赖库版本不匹配、权限问题等导致的。以下是一些常见的解决方法: 检查网络连接:首先...
    99+
    2024-04-02
  • VUE 第三方登录:常见问题与解决方案
    第三方登录按钮不显示 问题描述:在页面上添加了第三方登录按钮,但按钮不显示。 解决方案: 检查按钮代码是否正确,确保按钮代码已正确添加到页面中。 检查按钮样式是否正确,确保按钮样式已正确添加到页面中。 检查第三方登录平台是否已正确...
    99+
    2024-02-23
    VUE 第三方登录 常见问题 解决方案 OAuth2.0
  • nginx 解决跨域问题嵌入第三方页面
    目录前言 困难 跨域定义 nginx 的特性 反向代理 动静分离 尝试实现 最终效果 题外话 前言 我们自己的系统需要加载第三方系统中的一部分组件。计划的是第三方开发、提供相关接口...
    99+
    2024-04-02
  • vue3如何按需加载第三方组件库详解
    前言 以Element Plus 为例,配置按需加载组件和样式。 环境 vue3.0.5 vite2.3.3 安装 Element Plus yarn add...
    99+
    2024-04-02
  • 如何解决RMAN-20207报错问题
    这篇文章将为大家详细讲解有关如何解决RMAN-20207报错问题,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。 RMAN-20207: UNTIL TIME or RE...
    99+
    2024-04-02
  • 如何解决git pull报错问题
    在使用Git进行代码管理时,经常会用到git pull命令来拉取最新的代码。但是,在使用git pull时,有时候会遇到报错的情况,如何解决这些问题呢?本文将从以下几个方面介绍如何解决git pull报错问题:分析错误信息查看git log...
    99+
    2023-10-22
  • 如何理解React受控组件Hooks方式
    这篇文章主要介绍“如何理解React受控组件Hooks方式”,在日常操作中,相信很多人在如何理解React受控组件Hooks方式问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”...
    99+
    2024-04-02
  • mac第三方软件无法删除如何解决
    如果Mac上的第三方软件无法删除,可以尝试以下解决方法: 重新启动电脑:有时候重新启动可以解决一些软件无法删除的问题。 尝试...
    99+
    2023-10-21
    mac
  • 如何解决mysql中workbench报错的问题
    这篇文章主要介绍如何解决mysql中workbench报错的问题,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!mysql 中workbench报错的解决办法:首先打开找到workbe...
    99+
    2024-04-02
  • composer依赖报错问题如何解决
    今天小编给大家分享一下composer依赖报错问题如何解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。composer依赖...
    99+
    2023-07-05
  • 如何解决安装thinkphp报错问题
    这篇文章主要介绍了如何解决安装thinkphp报错问题的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇如何解决安装thinkphp报错问题文章都会有所收获,下面我们一起来看看吧。一、错误提示在安装ThinkPHP...
    99+
    2023-07-05
  • 如何解决使用bootstrap的dropdown部件时报错的问题
    这篇文章主要介绍了如何解决使用bootstrap的dropdown部件时报错的问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。问题描述:使...
    99+
    2024-04-02
  • 如何解决Node安装报错问题
    Node.js是一款基于Chrome V8引擎的JavaScript运行环境。它可以在服务器端运行JavaScript代码,具有高效、易学、跨平台等多种优点,因此广泛应用于后端开发、前端构建等领域。但是,在使用Node.js时,有时会遇到安...
    99+
    2023-05-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作