How to avoid `loaded two copies of React` error wh

2019-02-05 16:11发布

问题:

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?

回答1:

I believe the answer is to specify react and react-dom as peerDependencies in your external component's package.json. As best as I can follow here and here, npm link should (as of npm@3) no longer install peerDependencies (or `devDependencies either).

Aaaand I just read your post more carefully and realized that you already are specifying them as peerDependencies. Therefore, I think the answer boils down to:

Upgrade to npm@3:

npm install -g npm@3.0-latest



回答2:

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'))

}


回答3:

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.



回答4:

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


回答5:

The problem is with npm link. https://github.com/npm/npm/issues/5875

npm doesn't treat the linked directory as a child of the parent project.

Try alternatives to npm link:

1) Use relative path dependencies in package.json

2) Manually include your dependencies in your projects node_modules directory

3) Use url path

Basically anything but npm link



回答6:

Adding the following in my webpack.config.js worked for me:

resolve: {
    alias: {
        react: path.resolve(__dirname, 'node_modules', 'react')
    }
}

I also experimented with DedupePlugin (mentioned as a possible remedy here) but I couldn't get it to work.

What's also interesting is that I've encountered different (and perhaps more insidious) manifestations of the same problem when a module is found in multiple places in the dependency graph.

One such case was that my React.PropTypes.instanceOf(SomeType) constraints would emit warnings even though the type I passed in was correct. That was due to the module being present in multiple places in the node_modules directory tree. Due to duck-typing the code would still work, but my console was cluttered with these warnings. Going the resolve.alias way silenced those too.

YMMV



回答7:

If you're using Webpack in the main project, this solution may work. In my case, project-a requires project-b. Both require React and ReactDOM 0.14.x

I have this in project-a/webpack.config.js:

resolve: {
  modulesDirectories: ['node_modules'],
  fallback: path.join(__dirname, 'node_modules')
},
resolveLoader: {
  fallback: path.join(__dirname, 'node_modules')
},
  • project-b requires React and ReactDOM as peerDependencies in project-b/package.json
  • project-a requires project-b as a devDependency (should also work required as a dependency) in project-a/package.json
  • local project-b is linked to project-a like so: cd project-a; npm link ../project-b

Now when I run npm run build within project-b, the changes appear immediately in project-a



回答8:

I am using ReactJS.net and setup webpack from the tutorial there and started using react-bootstrap aswell when i started getting this error. I found adding 'react-dom': 'ReactDOM' to the list of externals in webpack.config.js fixed the problem, the list of externals then looked like this:

  externals: {
    // Use external version of React (from CDN for client-side, or
    // bundled with ReactJS.NET for server-side)
      react: 'React',
      'react-dom': 'ReactDOM'

This seems to be the first stack overflow link on google for this error, so i thought this answer might help someone here.



回答9:

I was getting this because I had already included react and react-dom as external scripts in my HTML markup.

The error was caused by adding an import ReactDOM from 'react-dom' to a component module. The error went away once I removed the import, and the module worked fine since the components were already available.



标签: reactjs npm