In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces "how to solve the Hooks error problem of third-party components". In daily operation, I believe many people have doubts about how to solve the problem of Hooks error reporting of third-party components. The editor consulted all kinds of materials and sorted out simple and easy-to-use methods of operation. I hope it will be helpful for you to answer the doubt of "how to solve the Hooks error problem of third-party components". Next, please follow the editor to study!
The incident happened
A requirement requires the introduction of a third-party component library.
When functional component An in the component library is introduced, React runs Times error:
"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...
From the React documentation, this is due to "misuse of Hooks".
There are three possible reasons for errors on the official website:
1.React and ReactDOM versions do not match
A version of ReactDOM above v16.8 is required to support Hooks.
Our project uses v17.0.2, which does not belong to this reason.
two。 Broke the rules of Hooks
Hooks can only be called at the top level of a function component or a custom Hooks.
If you look at the source code of component A, you can see that the error is a top-level called useRef:
Function A () {/ /... Var xxxRef = useRef (null); / /...}
It doesn't belong to that reason.
3. Duplicate React
Recorded from the React document:
In order for Hook to work properly, the react dependency in your application code and the react dependency used internally in react-dom 's package must be resolved to the same module.
If these react dependencies resolve to two different exported objects, you will see this warning. This may happen when you accidentally introduce two package copies of react.
It's easy to read, and this one seems to be the most suspected.
Positioning problem
Type a breakpoint in the useRef that reported the error and find that it comes from:
Http://localhost:8081/Users/ Project Directory / node_modules/ component Library / node_modules/react/cjs/react.development.js
Make breakpoints in other places in the project where Hooks is called but not reported wrong, and find that the resources come from:
Http://localhost:8081/Users/ project directory / node_modules/react/cjs/react.development.js
The useRef that reported the error and other Hooks of the project refer to a different react.development.js.
Looking through the package.json of the component Library, he found that he installed react and react-dom as dependencies:
"dependencies": {"react": "^ 16.13.1", "@ babel/runtime-corejs3": "^ 7.11.2", "react-dom": "^ 16.13.1"}
This creates the two dependencies under node_modules in the component Library directory.
As a "component library", this is obviously not appropriate.
Temporary solution
The best thing to do is to use these two dependencies as peerDependencies, that is, as external dependencies.
In this way, when we introduce the component Library, the component Library will use the react and react-dom from our project instead of installing one.
But I do not have the permission of this "component library", so I can only make articles in my own project.
A configuration item, resolutions, is provided in the package.json documentation to temporarily solve this problem.
Resolutions allows you to copy a version of a package that is nested and referenced in the project node_modules.
Make the following changes in the package.json of our project:
/ / Project package.json {/ /... "resolutions": {"react": "17.0.2", "react-dom": "17.0.2"}, / /.}
In this way, both dependencies used in the project will use the version specified in resolutions.
Whether it is the component Library or the react and react-dom in our project code, they all point to the same file.
Now the problem has been solved temporarily, but what is the cause of the problem?
Let's dig inside the Hooks source code to find the answer.
Deep into the source code
First of all, let's consider two questions:
When we call another Hooks within one Hooks, we report the error mentioned at the beginning.
For example, the following code will report an error:
Function App () {useEffect (() = > {const a = useRef ();}, []) / /...}
Hooks is just a function. How does he perceive that he is executing inside another Hooks?
As in the example above, how does useRef perceive that it is executing in the callback function of useEffect?
Looking at another problem, we know that classComponent has two lifecycle functions, componentDidMount and componentDidUpdate, to distinguish between mount and update.
So Hooks as a function, how can you tell the difference between mount and update?
Obviously, there is a mechanism within the Hooks source code that can perceive the context of the current execution.
gradually entering blissful circumstances
In the browser environment, we will refer to the react and reactDOM packages.
Where there is a variable ReactCurrentDispatcher in the code of the react package.
His current parameter points to the Hooks context currently in use:
Var ReactCurrentDispatcher = {/ * @ internal * @ type {ReactComponent} * / current: null}
At the same time, in reactDOM, during the running of the program, ReactCurrentDispatcher.current will point to different references according to the current context.
For example:
Var HooksDispatcherOnMountInDEV = {useState: function () {/ /...}, useEffect: function () {/ /...}, useRef: function () {/ /...}, / /...} var HooksDispatcherOnUpdateInDEV = {useState: function () {/ /...}, useEffect: function () {/ /...}, useRef: function () {/ /...} / /...} / /...
When you are in the mount environment of DEV, ReactCurrentDispatcher.current points to HooksDispatcherOnMountInDEV.
When you are in the update environment of DEV, ReactCurrentDispatcher.current points to HooksDispatcherOnUpdateInDEV.
Let's look at the definition of useRef:
Function useRef (initialValue) {var dispatcher = resolveDispatcher (); return dispatcher.useRef (initialValue);}
The internal call is dispatcher.useRef.
Dispatcher is ReactCurrentDispatcher.current.
Function resolveDispatcher () {var dispatcher = ReactCurrentDispatcher.current; if (! (dispatcher! = = null)) {{throw Error ("Invalid hook call.");}} return dispatcher;}
As you can see, the error at the beginning is precisely because it is thrown when dispatcher is null
This is why Hooks can distinguish between mount and update.
Similarly, in the DEV environment, when a Hooks is executing, the ReactCurrentDispatcher.current points to the reference-- InvalidNestedHooksDispatcherOnUpdateInDEV.
The Hooks that is called again in this case, such as the following useRef:
Var InvalidNestedHooksDispatcherOnUpdateInDEV = {/ /... UseRef: function (initialValue) {currentHookNameInDev = 'useRef'; warnInvalidHookAccess (); updateHookTypesDev (); return updateRef ();}, / /...}
WarnInvalidHookAccess error message will be executed internally, indicating that it has been executed in another Hooks.
The truth has become known to all
Here we finally know the essential cause of the problem mentioned at the beginning:
Because the component Library uses dependencies instead of peerDependencies, the react and reactDOM referenced in the component Library are files under the component Library directory node_modules.
The react and reactDOM used in the project are files under the project directory node_modules.
React in the component Library and react in the project directory initialize ReactCurrentDispatcher at run time, respectively.
These two ReactCurrentDispatcher depend on the reactDOM of the corresponding directory respectively.
We execute the ReactDOM.render method of reactDOM in the project directory, and it will change the direction of the ReactCurrentDispatcher.current under the react package in the project directory as the program runs.
The ReactCurrentDispatcher.current in the component Library is always null
When calling Hooks in the component Library, an error is reported because ReactCurrentDispatcher.current is always null
At this point, the study on "how to solve the Hooks error problem of third-party components" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.