javascript - Jak spojit typy props v znovupoužitelné knihovně komponent React
Snažím se pro zábavu vytvořit jednoduchou knihovnu React komponent pomocí Typescriptu a Storybooku a moje první hloupá komponenta Button se zdá fungovat. Mám další demo aplikaci CRA, kde zkouším knihovnu jako konečný uživatel.
Mám ale problém s jednou věcí: nemohu rozchodit prop-types mého Button komponentu v demo aplikaci. Prostě to nevypisuje žádná varování.
Některé další podrobnosti:
Soubory a složky knihovny jsou v současné době uspořádány následovně:
src/
index.ts
controls/
index.ts
Button.tsx
babelconfig.js
tsconfig.ts
webpack.config.js
(+ other configuration files and folder for jest and storybook)
Mám soubor src/index.ts, který je vstupním bodem mé knihovny a jen exportuje vše, co pochází ze složky controls.
// src/index.ts
export * from './controls'
V mých složkách src/controls je soubor index.ts, který exportuje vše z komponenty Button.
// src/controls/index.ts
export * from './Button'
Komponenta Button je v tuto chvíli tak jednoduchá jako:
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 }
Vše je svázáno pomocí webpack 4.41 s tímto konfiguračním souborem:
// 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/
}
]
}
}
Moje konfigurace babel je tato:
// babel.config.js
module.exports = {
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-typescript'
],
env: {
test: {
plugins: [ 'require-context-hook' ]
}
}
}
Nejsem si jistý, jestli to může mít význam, ale toto je můj konfigurační soubor typescript 3.7:
// 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
}
}
Hlavní vlastnosti mého souboru package.json jsou tyto:
// 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
Očekávání
V mé demo aplikaci, vytvořené pomocí npx create-react-app sadsui-demo, jsem nainstaloval balíček do mého package.json s závislostí takto:
// package.json
"sads-ui": "file:../sads-ui/sads-ui-0.1.0.tgz"
Používám Button v mém App.js následovně:
import React from 'react'
import { Button } from 'sads-ui'
const App = () => (
<div className="App">
<Button />
</div>
)
export default App
Očekával bych, že dostanu varování, které mi řekne, že vlastnost text u Button je povinná, ale nedostanu nic. Prázdné tlačítko je však správně zobrazeno.
Mé uvažování
Jsem nějak v temnotě, ale něco mám na mysli, nejsem si jistý, zda to dává nějaký smysl, taky proto, že to ani nefunguje.
Myslím, že sestavení knihovny v režimu webpack production může z balíčku knihovny odstranit prop-types, takže je nemám k dispozici, když používám komponenty v konečných aplikacích.
Zkoušel jsem balit v režimu development, vidím v dist/index.js kód prop-types, ale ať dělám cokoli, nefunguje to... :(
Odpověď č. 1
Váš webpack kompiluje (vše, co odpovídá *.tsx) do JavaScriptu při sestavování knihovny, a když ji importujete do svého create-react-app, je to jen JavaScript (měli byste se podívat do svého /node_modules/ ve vašem create-react-app a skutečně se sami přesvědčit, jak vaše knihovna vypadá)
Ve vaší knihovně můžete exportovat samostatné soubory index.d.ts (nebo Button.d.ts nebo cokoliv jiného) pro vaše komponenty, které nejsou kompilovány do JS, a které si spotřebitelé mohou importovat (vždy je dobré se podívat na jiné projekty a zjistit, jak to dělají. Zde je index.d.ts z Material UI, pravděpodobně můžete být mnohem přehlednější než oni tím, že budete mít Button.d.ts, který je importován do index.d.ts a pak exportován jako jeden velký modul TypeScript knihovny).