My work is making a React UI Kit/Component Library to be used internally for our products. Everything is working fine while developing and displaying on Storybook.
While testing the library in a generic project out-of-the-box from create-react-app, importing and implementing the components made without React Hooks are alright, but soon as we use the ones made with Hooks - the Invalid Hook Call error shows: https://reactjs.org/warnings/invalid-hook-call-warning.html
Have tried everything listed there(and read and tried the github thread solutions linked on the page), and the component simply used useRef()
and nothing else so we know no rules were broken, React and React-dom versions are up to date, and running npm ls react
and npm ls react-dom
in the project results in [email protected]
and [email protected]
and nothing else... So it doesn't seem like we have multiple React's?
Any help would be much appreciated!!
This is the UI Kit's package.json
{
"name": "react-ui-kit",
"version": "0.0.15",
"description": "UI Kit",
"main": "dist/index",
"module": "dist/index",
"typings": "dist/index",
"jest": {
"setupFilesAfterEnv": [
"<rootDir>/setupTests.js"
],
"coverageReporters": [
"json-summary",
"text",
"lcov"
]
},
"scripts": {
"test": "jest --coverage",
"test:badges": "npm run test && jest-coverage-badges input './coverage/coverage-summary.json' output './badges'",
"test-update": "jest --updateSnapshot",
"lint:css": "stylelint './src/**/*.js'",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook -c .storybook -o .out",
"generate": "plop --plopfile ./.plop/plop.config.js",
"build": "webpack --mode production",
"prepare": "npm run build",
"prepublishOnly": "npm run test:badges",
"storybook-docs": "build-storybook --docs",
"todo": "leasot './src/**/*.js'",
"todo-ci": "leasot -x --reporter markdown './src/**/*.js' > TODO.md"
},
"license": "ISC",
"peerDependencies": {
"prop-types": "^15.7.2",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"recharts": "^1.7.1",
"styled-components": "^4.3.2",
"styled-normalize": "^8.0.6"
},
"devDependencies": {
"@babel/cli": "^7.6.0",
"@babel/core": "^7.6.0",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/preset-env": "^7.6.0",
"@babel/preset-react": "^7.0.0",
"@storybook/addon-actions": "^5.2.1",
"@storybook/addon-docs": "^5.2.1",
"@storybook/addon-info": "^5.2.1",
"@storybook/addon-knobs": "^5.2.1",
"@storybook/addon-links": "^5.2.1",
"@storybook/addon-viewport": "^5.2.1",
"@storybook/addons": "^5.2.1",
"@storybook/react": "^5.2.1",
"babel-eslint": "^10.0.3",
"babel-jest": "^24.9.0",
"babel-loader": "^8.0.6",
"babel-plugin-styled-components": "^1.10.6",
"eslint": "^6.5.1",
"eslint-plugin-react": "^7.15.0",
"eslint-plugin-react-hooks": "^2.1.1",
"jest": "^24.9.0",
"jest-coverage-badges": "^1.1.2",
"jest-styled-components": "^6.3.3",
"leasot": "^8.2.0",
"plop": "^2.4.0",
"polished": "^3.4.1",
"prop-types": "^15.7.2",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-test-renderer": "^16.9.0",
"recharts": "^1.7.1",
"storybook-styled-components": "github:merishas/storybook-styled-components",
"styled-components": "^4.4.0",
"styled-normalize": "^8.0.6",
"stylelint": "^10.1.0",
"stylelint-config-recommended": "^2.2.0",
"stylelint-config-styled-components": "^0.1.1",
"stylelint-processor-styled-components": "^1.8.0",
"webpack": "^4.40.2",
"webpack-cli": "^3.3.9"
},
"files": [
"dist"
],
}
The UI Kit's webpack.config.js
const path = require('path');
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve('dist'),
filename: 'index.js',
libraryTarget: 'commonjs2',
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /(node_modules)/,
use: 'babel-loader',
},
{
test: /\.(eot|svg|ttf|woff|woff2|otf)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
limit: 10000,
mimetype: 'application/font-woff',
},
},
],
},
],
},
resolve: {
alias: {
components: path.resolve(__dirname, 'src/components/'),
utils: path.resolve(__dirname, 'src/utils/'),
themes: path.resolve(__dirname, 'src/themes/'),
},
extensions: ['.js', '.jsx'],
},
devtool: false,
};
How components are imported and implemented in project:
import React from "react";
import logo from "./logo.svg";
import "./App.css";
import { FieldLabel, Button } from "react-ui-kit";
function App() {
return (
<div className="App">
<FieldLabel>THIS IS THE ONE USING the useRef Hook</FieldLabel>
<Button>This component is totally fine without FieldLabel, this isn't using Hooks</Button>
</div>
);
}
export default App;
Looking at the webpack config, I could see that, UI kit is getting bundled with react
included which might be causing the issue.
To avoid this you could use webpack externals.
https://webpack.js.org/configuration/externals/
The externals configuration option provides a way of excluding dependencies from the output bundles. Instead, the created bundle relies on that dependency to be present in the consumer's environment. This feature is typically most useful to library developers, however there are a variety of applications for it.
So you could update UI Kit webpack config to not include react
and the peerDependencies should take care of the dependency handling for any consumers of the library.
Updated webpack.config
const path = require("path");
module.exports = {
mode: "production",
entry: "./src/index.js",
output: {
path: path.resolve("dist"),
filename: "index.js",
libraryTarget: "commonjs2"
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /(node_modules)/,
use: "babel-loader"
},
{
test: /\.(eot|svg|ttf|woff|woff2|otf)$/,
use: [
{
loader: "file-loader",
options: {
name: "[name].[ext]",
limit: 10000,
mimetype: "application/font-woff"
}
}
]
}
]
},
resolve: {
alias: {
components: path.resolve(__dirname, "src/components/"),
utils: path.resolve(__dirname, "src/utils/"),
themes: path.resolve(__dirname, "src/themes/")
},
extensions: [".js", ".jsx"]
},
externals: {
// Use external version of React
react: "react"
},
devtool: false
};
I have published a test package to confirm this (react-ui-kit-dontuse).
Demo links
v0.0.21(Without webpack externals)
https://stackblitz.com/edit/react-xyjgep
v0.0.23(With webpack externals)
https://stackblitz.com/edit/react-ihnmrl
Source code of test package: https://github.com/nithinthampi/react-ui-lib-test
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With