React组件库中使用hooks异常: Invalid hook call. Hooks can only be called inside of the body of a function component.

问题描述

最近有个低代码项目需要开发,因为在两个项目中使用到了多个业务重合度比较高的组件,所以准备创建一个组件库来编写这些组件,然后在两个项目中引用。

如果在项目直接使用发布好的依赖包,那将不会产生任何问题。开发过程中,编写纯函数的业务组件时没有发生任何问题,当在组件中使用到了hooks时报出了如下异常:

Uncaught Invariant Violation: 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

按照异常栈描述的提示:hooks只能在函数组件的组件体中使用。并给出了三个可能的原因:

  1. react和react-dom的版本可能不匹配
  2. hooks的使用规则有问题
  3. 在一个项目中可能有多个react副本。

解决过程

开始没有任何思路来处理这个问题[破涕为笑],直到后面在Stack Overflow上看到了有人遇到了相同的问题。从Stack Overflow问题的答案,和在答案中看到的github的相关issue以及在答案中看到的相关官方文档对这个问题的解释,确定了问题确实是由于重复的React引起的。

异常原因

In order for Hooks to work, the react import from your application code needs to resolve to the same module as the react import from inside the react-dom package.

项目中的react引用要和react-dom包内部的react使用同一个引用,注意这里说的是引用,那就必须是同一个react,哪怕是使用的版本完全一样也是不可以的。

可以通过两种方式来确实究竟是不是这个原因:

  1. 在项目的根目录下执行npm ls react, 查看是都出现了多个结果,如果有多个那说明产生了问题
  2. 可以在代码中进行判断react是否使用了相同的引用,如果结果为false,则说明产生了问题
// Add this in node_modules/react-dom/index.js
window.React1 = require('react');

// Add this in your component file
require('react-dom');
window.React2 = require('react');
console.log(window.React1 === window.React2);

解决方案

  1. 在引用组件库的项目中
cd node_modules/react
npm link
  1. 在组件库项目中的根目录下执行
npm link react

引用

https://stackoverflow.com/questions/57145261/link-react-versions-between-linked-library-and-workspace-application

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

https://legacy.reactjs.org/warnings/invalid-hook-call-warning.html

浙ICP备2023004975号-2
浙公网安备33011002017713号