簡體   English   中英

TypeScript + React:元素類型無效:預期為字符串(對於內置組件)

[英]TypeScript + React: Element type is invalid: expected a string (for built-in components)

我意識到有幾個與此錯誤有關的問題,但據我所知這是一種獨特的情況,與不正確的import語句無關。

我正在使用TypeScriptwebpack構建一個React組件庫。

我的目錄結構:

- src
  - index.ts
  - components
    - Button
      - Button.tsx
      - index.ts
      - Button.css
      - Button.d.css (generated by webpack plugin)
- package.json
- tsconfig.json
- webpack.config.js
- postcss.config.js

我的tsconfig.json

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "module": "es2015",
    "target": "es5",
    "lib": ["es6", "dom"],
    "sourceMap": true,
    "allowJs": false,
    "jsx": "react",
    "moduleResolution": "node",
    "rootDir": "src",
    "outDir": "dist",
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "declaration": true
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "build",
    "dist",
    "scripts",
    "acceptance-tests",
    "webpack",
    "jest",
    "src/setupTests.ts",
    "**/*/*.test.ts",
    "examples"
  ]
}

我的webpack.config.js

const path = require("path");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: "./src/index.ts",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "index.js"
  },
  mode: "development",
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: "awesome-typescript-loader",
      },
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'typings-for-css-modules-loader',
            options: {
              modules: true,
              namedExport: true,
              banner: "/* This file is generated during the webpack build. Please do not edit/remove. */",
              localIdentName: '[name]__[local]'
            }
          },
          {
            loader: 'postcss-loader',
            options: {
              config: {
                path: './postcss.config.js'
              }
            }
          }
        ]
      },
      {
        test: /\.(jpg|png|gif|svg)$/,
        use: [
          {
            loader: "file-loader",
            options: {
              name: "[name].[ext]"
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css"
    })
  ],
  devtool: "source-map",
  resolve: {
    extensions: [".js", ".ts", ".tsx", ".css"]
  }
};

我的postcss.config.js

module.exports = {
    modules: true,
    plugins: [
        require('precss'),
        require('postcss-simple-vars'),
        require('autoprefixer'),
        require('postcss-nested'),
    ]
}

src/index.ts很簡單:

import { Button } from './components/Button';

export {
  Button,
};

src/components/Button/index.ts

import Button from './Button';

export { Button };

src/components/Button/Button.tsx

import * as React from 'react';
import { ReactNode } from 'react';
import { Link } from 'react-router-dom';
import * as styles from './Button.css';

export interface IButtonPropTypes {
  onClick?: React.MouseEventHandler<any>;
  label: string;
  children?: ReactNode[] | string;
  kind?: 'link' | 'action';
  style?: { [key: string]: string };
  href?: string;
  target?: string;
  className?: string;
}

export default function Button({
  onClick,
  label,
  children,
  kind = 'action',
  style = {},
  href,
  target,
  className,
}: IButtonPropTypes) {
  const text = label || children;
  const kindStyle = styles[kind] || '';
  const classes = className || '';
  if (href) {
    return (
      <Link
        className={`${style.btn} ${kindStyle} ${classes}`}
        to={href}
        target={target}
        onClick={onClick}
        style={style}
      >
        <span className={style.background} />
        <span>{text}</span>
      </Link>
    );
  }

  return (
    <button className={`${style.btn} ${kindStyle}`} onClick={onClick} style={style}>
      <div>{text}</div>
    </button>
  );
}

運行webpack后,我的dist文件夾如下所示:

- dist
  - index.js
  - index.js.map
  - index.d.ts
  - main.css
  - main.css.map
  - components
    - Button
      - Button.d.ts
      - index.d.ts

dist/index.js似乎是由webpack正確編譯的。 package.json ,我有:

  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "files": ["dist"]

運行yarn link ,我在一個獨立的應用程序中導入並使用Button組件,如下所示:

import { Button } from 'my-components';

class App extends React.Component {
  render() {
    return (
      <div className="App">
        <Button label="click me" />
      </div>
    );
  }
}

export default App;

並收到以下錯誤:

 Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: 

未定義。 您可能忘記了從定義文件中導出組件,或者可能混淆了默認導入和命名導入。

 Check the render method of `App`. 

如果刪除Button組件,則App呈現沒有任何錯誤。

通過將一次性模塊發布到npm產生相同的錯誤。

此外,如果有人對捆綁此庫的更好方法有任何建議,我很想聽聽他們的建議,因為這是我第一次使用postcss

似乎在導入index.ts犯了一個小錯誤。 由於這是默認導出,因此不應該使用花括號。

import Button from './components/Button';

事實證明,這是由於我的webpack配置出現問題。 添加以下行以output可修復錯誤:

  output: {
    . . . 
    library: "opentok-ux-components",
    libraryTarget: 'umd',
    umdNamedDefine: true
  },

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM