Questions lead

Today, when running the react project, the browser threw a strange error:

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:
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
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.
Copy the code

Why is it strange? Because this project can run before, I re-installed a dependency can not run, is really happy to see 😒.

React-hooks error: This is caused by a react-hooks error, which is caused by a component that I packaged and installed using the NPM package. Once you remove this component from your project, the error goes away, but it’s up to Google to figure out what went wrong.

Sure enough, someone had the same problem as I did, and the react website provided a detailed description of the error:

It may be caused by the following reasons:

  • React and React DOM versions do not match

  • You can only call a Hook when rendering a React function component:

    • βœ… calls them at the top level of function components.
    • βœ… calls them at the top level of custom hooks.
  • Duplicate the React

For the first point, the official website explains that it is possible to use the React -dom version (<16.8.0) that does not support React Hook. This can be ruled out by checking the React -dom version number in package.json.

The second point is about Hooks, because this code has successfully run before and can be definitively checked out.

Finally, there is the third point, which is described in detail on the official website:

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.

If these react imports resolve to two different exports objects, you will see this warning. This may happen if you accidentally end up with two copies of the react package.

In order for the Hook to work properly, the React dependencies in the application code and the React dependencies used within the React-DOM package must be resolved into the same module. If these React dependencies resolve into two different exported objects, you’ll see this warning. The version numbers of the react and react-dom components that I encapsulated were inconsistent with the versions of the React and react-dom components that the main project relied on.

Finding the cause of the error, what can be done to solve it?

Now the desired effect is:

The versions of the react and react-dom dependencies in my packageA should be the same as the versions of the React and react-dom installed on the main system. You should rely on react and react-DOM in the main system.

As I continued through the document, one sentence caught my attention:

For example, maybe a library you’re using incorrectly specifies react as a dependency (rather than a peer dependency).

I am prompted that the library I am using may incorrectly specify React as a dependency (instead of peer Dependency).

Json configuration item called peerDependencies. If you have a package.json configuration item called peerDependencies, you need to add peerDependencies.

I met peerDependencies

PeerDependencies are often used in the development of some plug-ins, such as jquery-UI development depends on jQuery, htML-webpack-plugin development depends on WebPack, etc.

To sum up the following characteristics:

  • The premise of the correct operation of the plug-in is that the core dependency library must be downloaded and installed first, and cannot be independently relied on and referenced from the core dependency library.
  • The design of plug-in entry API must conform to the specification of core dependent library.
  • The core logic of the plug-in runs in calls to the dependent library;
  • In practice, under the same plug-in system, it is better to have the same version of the core dependency library;

For example 🌰 :

Let’s say we have a helloWorld project that already declares packageA in its package.json dependencies. Plugin1 and plugin2 also depend on packageA. If you declare packageA with dependencies instead of peerDependencies, $NPM install will install plugin1 and plugin2 dependency graphs like this:

.β”œ ── β”œβ”€ β”œβ”€ β”‚ β”œβ”€ β”‚ β”œβ”€ β”‚ β”œβ”€ β”‚ β”œβ”€ β”‚ β”œβ”€ β”‚ β”œβ”€ β”‚ β”œβ”€ β”‚ β”œβ”€ β”‚ β”œβ”€ β”‚ β”œβ”€ β”‚ β”œβ”€ β”‚ β”œβ”€ β”‚ β”œ ─ garbage ─ garbage β”‚ β”œ ─ garbageCopy the code

Install packageA in plugin1 and plugin2. Install packageA in plugin1 and plugin2. Two installations are redundant.

PeerDependency, on the other hand, avoids the problem of similar core dependency libraries being downloaded repeatedly.

If you use peerDependency to declare the core dependency libraries in package.json in plugin1 and plugin2, for example:

plugin1/package.json

{
  "peerDependencies": {
    "packageA": "1.0.1"}}Copy the code

plugin2/package.json

{
  "peerDependencies": {
    "packageA": "1.0.1"}}Copy the code

Declare packageA on the main system:

helloWorld/package.json

{
  "dependencies": {
    "packageA": "1.0.1"}}Copy the code

When $NPM install is executed on the main system, the dependency graph looks like this:

.β”œ ── helloWorld β”‚ β”œβ”€β”€ β”œβ”€ β”‚ β”œβ”€ β”œβ”€ β”œ 2Copy the code

As you can see, the generated dependency graph is flat and packageA is installed only once.

Use dependencies to declare a library of dependencies:

  • If the user explicitly relies on the core library, the plug-in’speerDependencyThe statement;
  • If the user does not explicitly rely on the core library, follow the plug-inpeerDependenciesThe declared version installs the library into the project root directory.
  • When the version that the user depends on and the version that each plug-in depends on are not compatible with each other, an error will be reported for the user to repair by himself.

conclusion

Now that you understand the use of peerDependencies, let’s go back to the question at the beginning.

React < span style = “box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; font-size: 14px! Important; word-spacing: 0px;

The main system package. Json

{
  "dependencies": {
    "react": "^ 16.13.1"."react-dom": "^ 16.13.1"}}Copy the code

Then declare react and react-dom versions in peerDependencies in the package.json component library:

The component package. The json

{
  "peerDependencies": {
    "react": "> = 16.12.0"."react-dom": "> = 16.12.0"}}Copy the code

After $NPM install is executed on the primary system, the primary system and the component library can share react and react-dom installed on the node_module of the primary system.

At this point, you can finally shout out “Ollie here!” , the problem is solved satisfactorily ღ(Β΄ α΄— Β· ‘).

More exciting content welcome to pay attention to my public number!