Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid `loaded two copies of React` error when developing an external component?

Tags:

npm

reactjs

I am developing an external component (let's say my-component, which I link to the project with npm link (as it is in process and I need the package to reflect changes).

In the my-component folder there are node_modules/react and node_modules/react-dom as they are its dependencies. However they are peerDependences, so I did not suppose to bring them into the project linking this package.

However when using npm link, it link the whole directory, including node_modules. So, when the project builds, it includes packages 2 times: from node_modules/* and from node_modules/my-component/node_modules/*.

This begins to affect when the component is using ReactDOM.findDOMNode, it causes this error:

Warning: React can't find the root component node for data-reactid value `.0.2.0`. If you're seeing this message, it probably means that you've loaded two copies of React on the page. At this time, only a single copy of React can be loaded at a time.

Also, it may help to understand what's happening: the problem only appears if there are both node_modules/my-component/node_modules/react and node_modules/my-component/node_modules/react-dom. If there is only one of them, there is no error message.

The usual package installation does not bring such error as there is no node_modules/react-dom there.

How is it supposed to develop an external component and the project at the same time?

like image 985
Varvara Stepanova Avatar asked Oct 15 '15 20:10

Varvara Stepanova


People also ask

How do you solve You might have more than one copy of React in the same app?

Method 1. In the module you are developing, add the conflicting packages to peerDependencies (and remove them from dependencies or devDependencies ): // package. json "peerDependencies": { "react": "16.13.

Can I use multiple React versions?

The React team said that there are no new features in React 17, but [email protected] comes with the power to lazy load and deep integrate multiple versions of React. This no-feature is larger than any feature, which is a stepping stone for a paradigm that allows modern new apps to coexist with existing legacy ones.

How do I unlink a node module?

You can “undo” the effects of npm link by simply removing the symbolic links. But there is a built in command for it, aptly called: npm unlink . Just run npm unlink --no-save <module_name> on your project's directory to remove the local symlink, and run npm unlink on the module's directory to remove the global symlink.

What is React is package?

React is a JavaScript library for building user interfaces. Declarative: React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes.


3 Answers

The issue is twofold:

  1. You cannot have 2 copies of react loaded.
  2. npm link creates a symlink, however the "require" doesnt respect the symlink and when it tries to navigate up the directory, it never finds the react of the parent project.

Solution:

All you have to do is link the react and react-dom in your component to that of parent project's node_modules folder.

Go to your component project and remove the react and react-dom then do

npm link ../myproject/node_modules/react
npm link ../myproject/node_modules/react-dom
like image 157
abhisekpaul Avatar answered Oct 19 '22 07:10

abhisekpaul


Fixed it by adding react-dom as an alias to my webpack config

alias: {

    react$: require.resolve(path.join(constants.NODE_MODULES_DIR, 'react')),
    'react-dom': require.resolve(path.join(constants.NODE_MODULES_DIR, 'react-dom'))

}
like image 43
Yuri Avatar answered Oct 19 '22 07:10

Yuri


Someone clevererer than I (@mojodna) came up with this solution: remove the duplicate dependencies from the external component, and resolve them with your project's copies of those deps.

Step 1: Remove the dependencies from your external component's node_modules

As @cleong noted, you can't just remove the deps from the external component's node_modules, because your project's build step will fail when it hits the now-missing dependencies in the external component.

Step 2: Add your project's node_modules to NODE_PATH

To fix this, you can append the project's node_modules to the NODE_PATH environment variable when running your build step. Something like e.g. this:

NODE_PATH=$(pwd)/node_modules/ npm start

(where npm start is your script that bundles your external component, via e.g. Browserify, Webpack, etc.)

In fact, you could always append that NODE_PATH addition to your build scripts, and it would work whether or not you've npm linked anything. (Makes me wonder if it shouldn't be default npm behavior...)

Note: I left my existing answer because there's some conversation there, and this is a different (and better) solution.

like image 5
ericsoco Avatar answered Oct 19 '22 07:10

ericsoco