可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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 link
ed 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:
- You cannot have 2 copies of react loaded.
- 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.