I'm trying to create an npm package with some React ponents that I use for virtually all of my projects. Here's the folder structure and file contents:
- /
- dist/
- bundle.js
- src/
- MyComponent.jsx
- index.js
- package.json
- webpack.config.js
- dist/
MyComponent.jsx
import React, { Component } from 'react';
class MyComponent extends Component {
render() {
return (
<p>Hello, world!</p>
);
}
}
export default MyComponent;
index.js
// eventually there will be more ponents imported/exported here
import MyComponent from './MyComponent.jsx';
exports.MyComponent = MyComponent;
webpack.config.js
module.exports = {
entry: './src/index.js',
output: {
path: './dist',
filename: 'bundle.js'
},
// some loaders...
};
package.json
{
"name": "my-library",
"files": [
"dist",
"src"
],
"main": "dist/bundle.js",
// the usual stuff...
}
This is my understanding of the process. First, I build the src files with webpack. This looks at /src/index.js, imports the MyComponent class, then exports it, making it available as MyComponent. This is all added to a bundle.js file in /dist.
Next, I pack the module with npm pack
. This creates an archive file with the /src and /dist directories in it.
Then I go over to my other project and run npm install ../path/to/archive/file
. This adds the module to my node_modules directory. The problem is that when I try to import and use MyComponent...
import React, { Component } from 'react';
import MyComponent from 'my-library';
class App extends Component {
render() {
console.log(<MyComponent />);
return (
<MyComponent />
);
}
}
export default App;
...and render that ponent, I get this warning and error:
Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for posite ponents). Check the render method of `App`.
Uncaught Error: Element type is invalid: expected a string (for built-in ponents) or a class/function (for posite ponents) but got: object. Check the render method of `App`.
The output of the console.log is a React object, but the type is Object
, which seems like what the warning is alluding to (it should be a string instead, I guess).
Any idea what I'm missing?
EDIT:
Well, I'm closer. I added library options to my webpack config:
output: {
library: 'my-library',
libraryTarget: 'umd'
}
...and then I was able to use the ponent like this:
import MyLibrary from 'my-library';
const MyComponent = MyLibrary.MyComponent;
But I don't want to have to do that for every ponent. My goal is this:
import { MyComponent, MyOtherComponent } from 'my-library';
I'm trying to create an npm package with some React ponents that I use for virtually all of my projects. Here's the folder structure and file contents:
- /
- dist/
- bundle.js
- src/
- MyComponent.jsx
- index.js
- package.json
- webpack.config.js
- dist/
MyComponent.jsx
import React, { Component } from 'react';
class MyComponent extends Component {
render() {
return (
<p>Hello, world!</p>
);
}
}
export default MyComponent;
index.js
// eventually there will be more ponents imported/exported here
import MyComponent from './MyComponent.jsx';
exports.MyComponent = MyComponent;
webpack.config.js
module.exports = {
entry: './src/index.js',
output: {
path: './dist',
filename: 'bundle.js'
},
// some loaders...
};
package.json
{
"name": "my-library",
"files": [
"dist",
"src"
],
"main": "dist/bundle.js",
// the usual stuff...
}
This is my understanding of the process. First, I build the src files with webpack. This looks at /src/index.js, imports the MyComponent class, then exports it, making it available as MyComponent. This is all added to a bundle.js file in /dist.
Next, I pack the module with npm pack
. This creates an archive file with the /src and /dist directories in it.
Then I go over to my other project and run npm install ../path/to/archive/file
. This adds the module to my node_modules directory. The problem is that when I try to import and use MyComponent...
import React, { Component } from 'react';
import MyComponent from 'my-library';
class App extends Component {
render() {
console.log(<MyComponent />);
return (
<MyComponent />
);
}
}
export default App;
...and render that ponent, I get this warning and error:
Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for posite ponents). Check the render method of `App`.
Uncaught Error: Element type is invalid: expected a string (for built-in ponents) or a class/function (for posite ponents) but got: object. Check the render method of `App`.
The output of the console.log is a React object, but the type is Object
, which seems like what the warning is alluding to (it should be a string instead, I guess).
Any idea what I'm missing?
EDIT:
Well, I'm closer. I added library options to my webpack config:
output: {
library: 'my-library',
libraryTarget: 'umd'
}
...and then I was able to use the ponent like this:
import MyLibrary from 'my-library';
const MyComponent = MyLibrary.MyComponent;
But I don't want to have to do that for every ponent. My goal is this:
import { MyComponent, MyOtherComponent } from 'my-library';
Share
Improve this question
edited Dec 21, 2016 at 15:08
jacobsowles
asked Dec 19, 2016 at 22:05
jacobsowlesjacobsowles
3,0037 gold badges37 silver badges56 bronze badges
2
-
Are you tried with:
import { MyComponent } from 'my-ponent';
? – saeta Commented Dec 20, 2016 at 1:12 -
I tried
import { MyComponent } from 'my-ponent';
andconst MyComponent = require('my-ponent').MyComponent;
and got the same warning/error in both cases. – jacobsowles Commented Dec 20, 2016 at 15:27
2 Answers
Reset to default 0You have to export your ponent from the ponent index.js file like shown below
import MyComponent from './MyComponent.jsx';
import MyOtherComponent from './MyOtherComponent.jsx';
export {
MyComponent,
MyOtherComponent
}
Then in your Main project, Import them using
import { MyComponent, MyOtherComponent } from 'my-library';
It looks like the issue is with how your package exports ponents. Your index.js uses:
exports.MyComponent = MyComponent;
This makes MyComponent a property of the default export, which is why you had to do:
import MyLibrary from 'my-library';
const MyComponent = MyLibrary.MyComponent;
The Fix Instead of using exports, try this in src/index.js:
export { default as MyComponent } from './MyComponent.jsx';
This way, when you import your package like this:
import { MyComponent } from 'my-library';
…it will work as expected.