Vyhledávání na webu

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).

Související články