Reputation: 1451
I am trying to publish a basic React component to my npm registry and trying to reuse it. I think I am not following proper way to distribute my react component. Here's what I have:
This is the directory structure:
MyReactPOC
-> main.jsx
-> .npmrc
-> package.json
-> webpack.config.js
main.jsx
import React from 'react';
class MyComponent extends React.Component {
render() {
return (
<div>
<p>Hello from MyComponent!!</p>
</div>
);
}
}
export default MyComponent
package.json
{
"name": "@pankaj/my-component",
"version": "1.0.7",
"description": "POC for importing a component",
"main": "./dist/bundle.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"prepublish": "webpack --config webpack.config.js"
},
"repository": {
"type": "git",
"url": "my git repo"
},
"author": "Pankaj",
"license": "ISC",
"dependencies": {
"react": "~15.5.4",
"react-dom": "~15.5.4"
},
"devDependencies": {
"babel-cli": "~6.24.1",
"babel-core": "~6.24.1",
"babel-loader": "~6.4.1",
"babel-preset-es2015": "~6.24.1",
"babel-preset-react": "~6.24.1",
"webpack": "~2.4.1"
}
}
webpack.config.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './main.jsx',
output: { path: path.join(__dirname, 'dist'), filename: 'bundle.js' },
module: {
loaders: [
{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
}
]
},
};
I import the module in another project using import MyComponent from '@pankaj/my-component'
.
When I use this component like
I get the following error:
React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it's defined in.
Please help me understand the right way to distribute the react components so that they can be used by other projects within my org.
Here is how I use this component:
ComponentUse.js
import React from 'react';
import ReactDOM from 'react-dom';
import MyComponent from '@pankaj/my-component';
ReactDOM.render(
<MyComponent/>,
document.getElementById('root')
);
I have an index.html that has the 'root' div.
Upvotes: 5
Views: 3833
Reputation: 790
After several days of searching, I believe microbundle effortlessly achieves this. Below is my build command:
"scripts": {
"build": "microbundle build --globals react=React,react-dom=ReactDOM --jsx cloneElement,createContext,isValidElement,useContext,useReducer --jsxFragment Fragment --jsxImportSource react",
"dev": "microbundle watch"
},
Upvotes: 0
Reputation: 1980
I wrote a full Medium story because I had the same issue as you and there is no information about it. Check it out: https://medium.com/@BrodaNoel/how-to-create-a-react-component-and-publish-it-in-npm-668ad7d363ce
The main fix is to add libraryTarget: 'umd'
in the webpack.config.js file
Upvotes: 1
Reputation: 81
If you export with es6 syntax with babel, your component will be in MyComponent.default namespace. To avoid this you should install:
npm i --save-dev babel-plugin-add-module-exports in your .babelrc?
and add it to the babel conf:
{
"presets": [ "es2015", "react"],
"plugins": ["add-module-exports"]
}
Upvotes: 0
Reputation: 101
Every react component needs a return statement. Add a return statement in your render function and it should work.
...
render() {
return (<div>...</div>)
}
You cannot directly render to the Dom from your react component, instead return it so that react can work with it.
In webpack, specify your output file as a library using output.library https://webpack.js.org/concepts/output/#output-library
Upvotes: 3