Reputation: 1342
I'm in the process of building a reusable react library that uses other react libraries as dependencies. And I'm using webpack as the build tool.
The challenge that I'm running into is when I import my library into my app, which is built with create-react-app, I get the following error:
addComponentAsRefTo(...): Only a ReactOwner can have refs.
You might be adding a ref to a component that was not created inside a component's `render` method,
or you have multiple copies of React loaded (details: https://facebook.github.io/react/warnings/refs-must-have-owner.html).
The problem, as I understand it, is that webpack is bundling an additional copy of react in my library at a conflicting version.
I've tried several suggestions, but none of them seem to work. I've tried to:
1. Add react as an alias in my webpack resolve: {
alias: {
'react' : path.resolve(__dirname, 'node_modules/react'),
},
modules: [path.join(__dirname, 'node_modules')],
extensions: [".js", ".jsx"]
},
2. Add react and react-dom as externals in webpack:
externals: {
'ReactCSSTransitionGroup': 'react/lib/ReactCSSTransitionGroup',
'react': {
commonjs: 'react',
commonjs2: 'react',
amd: 'react',
umd: 'react',
root: 'React'
},
'react-dom': {
commonjs: 'react-dom',
commonjs2: 'react-dom',
amd: 'react-dom',
umd: 'react-dom',
root: 'ReactDOM'
}
},
3. Also tried adding react as a devDependency and peerDependency in package.json.
If I delete the node_modules folder while the library is linked up to the app, it starts working. This obviously isn't a solution, but more of a hint that it's pulling in an extra copy of react from the node_modules. As soon as I run npm i
the problem returns.
Here's my full webpack:
const path = require('path')
const SRC_DIR = path.resolve(__dirname, 'src')
const DIST_DIR = path.resolve(__dirname, 'dist')
module.exports = {
entry: SRC_DIR + '/index.js',
output: {
path: DIST_DIR,
filename: 'index.js',
libraryTarget: 'umd'
},
resolve: {
alias: {
'react' : path.resolve(__dirname, 'node_modules/react'),
},
modules: [path.join(__dirname, 'node_modules')],
extensions: [".js", ".jsx"]
},
resolveLoader: {
modules: [path.join(__dirname, 'node_modules')]
},
externals: {
'ReactCSSTransitionGroup': 'react/lib/ReactCSSTransitionGroup',
'react': {
commonjs: 'react',
commonjs2: 'react',
amd: 'react',
umd: 'react',
root: 'React'
},
'react-dom': {
commonjs: 'react-dom',
commonjs2: 'react-dom',
amd: 'react-dom',
umd: 'react-dom',
root: 'ReactDOM'
}
},
module: {
loaders: [
{ test: /\.css$/, loader: 'style-loader!css-loader' },
{
test: /\.js?/,
include: SRC_DIR,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react', 'stage-0'],
plugins: [
'transform-class-properties',
'transform-object-rest-spread'
]
}
}
]
}
};
And my package.json:
{
"name": "test-library",
"version": "1.0.0",
"main": "dist/index.js",
"scripts": {
"start": "webpack --progress --colors --watch",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"babel-core": "6.26.0",
"babel-loader": "7.1.2",
"babel-plugin-react-css-modules": "3.2.1",
"babel-plugin-transform-class-properties": "6.24.1",
"babel-plugin-transform-object-rest-spread": "6.26.0",
"babel-plugin-transform-runtime": "6.23.0",
"babel-preset-es2015": "6.24.1",
"babel-preset-react": "6.24.1",
"babel-preset-stage-0": "6.24.1",
"react": "^15.0.0",
"react-bootstrap-table": "4.0.2",
"react-dom": "15.6.1"
}
}
I've also created two repos to reproduce the bug, one is the test app, and one is the test library. To reproduce:
Clone the app and library and run npm i
:
app: https://github.com/scottmcpherson/test-app
library: https://github.com/scottmcpherson/git-library
cd into the library and run npm link
cd into the app and run npm link test-library
cd back into the app and run npm start
You should see the error appear in the browser. If you open the app in the your editor and look App.js you can see where I'm trying to import test-library.
This error only happen because the library depends on react-bootstrap-table
. If I comment out that module and just render a normal jsx table, everything works find.
Upvotes: 3
Views: 2413
Reputation: 4322
According to documentation to avoid dependencies duplication you can try this:
new webpack.optimize.CommonsChunkPlugin({
name: 'common'
})
Upvotes: 0