I'm trying to make a simple React components library for fun using Typescript and Storybook, and my first silly Button
component seems to work. I have another CRA demo app where I am trying the library as a final user.
I am stuck with a thing though: I can't make the prop-types
of my Button
component to work in the demo application. It just doesn't print the warnings.
Files and folder of the library are currently organized as follows:
src/
index.ts
controls/
index.ts
Button.tsx
babelconfig.js
tsconfig.ts
webpack.config.js
(+ other configuration files and folder for jest and storybook)
I have an src/index.ts
file which is the entry point of my library and it just exports everything that comes from the controls
folder.
// src/index.ts
export * from './controls'
In my src/controls
folders there's an index.ts
file which exports everything from the Button
component.
// src/controls/index.ts
export * from './Button'
The Button
component, at the moment, is as simple as:
import React from 'react'
import t, { InferProps } from 'prop-types'
const propTypes = {
text: t.string.isRequired
}
const Button = ({ text }: InferProps<typeof propTypes>) => (
<button>
{ text }
</button>
)
Button.propTypes = propTypes
export { Button }
Everything is bundled with webpack 4.41
with this configuration file:
// webpack.config.js
const path = require('path')
module.exports = {
mode: 'production',
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js',
library: 'sads-ui',
libraryTarget: 'umd'
},
externals: [
'react'
],
resolve: {
extensions: [ '.ts', '.tsx', '.js' ]
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
}
}
My babel
configuration is this one:
// babel.config.js
module.exports = {
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-typescript'
],
env: {
test: {
plugins: [ 'require-context-hook' ]
}
}
}
I'm not sure if it may matter, but this is my typescript 3.7
configuration file:
// tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "es6",
"jsx": "react",
"declaration": true,
"outDir": "./dist",
"downlevelIteration": true,
"strict": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"baseUrl": ".",
"typeRoots": [ "node_modules/@types" ],
"esModuleInterop": true
}
}
The main properties of my package.json
file are these one:
// other properties
"main": "dist/index.js",
"files": [
"dist/*",
"!dist/**/*.stories.d.ts"
],
"scripts": {
"prebuild": "rimraf ./dist ./*.tgz",
"build": "webpack",
"prepack": "npm run build",
"test": "jest",
"storybook": "start-storybook"
},
// other properties
In my demo app, created with npx create-react-app sadsui-demo
, I installed the package in my package.json
with a dependency like this:
// package.json
"sads-ui": "file:../sads-ui/sads-ui-0.1.0.tgz"
I use the Button
in my App.js
as follow:
import React from 'react'
import { Button } from 'sads-ui'
const App = () => (
<div className="App">
<Button />
</div>
)
export default App
I would expect to get a warning the tells me that the text
prop of Button
is required, but I get nothing. An empty button is correctly shown though.
I'm somehow in the dark but I have something in mind, not sure if it makes any sense, also because it doesn't seem to work either.
I think that building the library in webpack
production
mode may strip off prop-types
from the library bundle thus I don't have them available when I use the components in final applications.
I tried to bundle in development
mode, I see in the dist/index.js
the prop-types
code but they aren't working no matter what... :(
Your webpack is compiling (everything matching *.tsx) to javascript when building the library, and when you import it into your create-react-app it is just javascript (you should go into your /node_modules/
in your create-react-app and actually see for yourself what your library looks like)
In your library, you can export separate index.d.ts
(or Button.d.ts
or whatever) files for your components that are not compiled to JS that consumers can import (Always good to look at other projects and see how they do it. Here is material ui's index.d.ts
, you can probably be a lot cleaner than that by having a Button.d.ts that is imported into the index.d.ts and then exported as one big library typescript module
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.