background

We are currently working on a Bulma based React component library, which relies on the React library internally.

At first I naturally added it directly as a project dependency:

yarn add react
Copy the code

During the development, link the project to the test application through YARN Link to preview the component effect.

When a component in the library uses a hook, an error message will be reported as follows:

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

Hooks are called illegally. Hooks are called in the wrong place.

Upon double-checking, the only possible reason for the error is rule 3: The React dependency in the project is not unique.

Using the following authentication method, the console returns false to prove that the error inference is correct.

// 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);
Copy the code

Just as I was scratching my head, the following sentence woke me up:

For example, maybe a library you’re using incorrectly specifies react as a dependency (rather than a peer dependency). Until that library is fixed, Yarn resolutions is one possible workaround.

The react component library relies on peerDependencies, which you need to declare as peerDependencies.

The initial peerDependencies

A brief description of peerDependencies is available on the Node.js website.

Our component library is called Nash-Design, and before using peerDependencies, the dependency tree after the project depends on the component library looks like this:

App ├ ─ ─ [email protected] └ ─ ┬ [email protected] └ ─ ─ [email protected]Copy the code

At this point, Ass-Design has its own copy of React to work with, without using external React dependencies.

In general, this is fine and everyone’s code doesn’t interfere with each other, but it can be problematic for application scenarios such as plug-ins and component libraries, which is the root cause of the above problems.

You may have noticed that peerDependencies are used in most plug-ins, such as in the webpack plugin html-webpack-plugin:

"peerDependencies": {
  "webpack": "^ 5.20.0"
}
Copy the code

It is intended to share a WebPack dependency with the user’s project.

NPM update < react > < peerDependencies >

├─ [email protected] ├─ [email protected]Copy the code

As you can see, the React dependency was installed only once, and the problem was resolved.

The React dependency is not found. This is because dependencies in peerDependencies are not installed by default.

external

Configure the External option for the packaging tool you use, which indicates additional dependencies that need to be installed.

For example, in the ESBuild configuration:

esbuild.build({
    entryPoints: 'entry'.outfile: 'outfile'.platform: 'browser'.bundle: true.format: 'esm'.minify: false.allowOverwrite: true.watch: true.target: 'es2020'.external: [ // Additional installed dependencies are required
      'react'.'react-dom',]});Copy the code

At this point, the startup program can run normally.

The last

Finally post the project address: github.com/nass-design…

The project aims to build a React UI framework for learning and communicating on the client side (not on the backend), with a full ecosystem to be considered in the future, including a built-in uI-style blog builder. Welcome you who love technology to build with me!