当前位置: 首页 > 知识库问答 >
问题:

在TypeScript中使用JS React组件:JSX元素类型'MyComponent'不是JSX元素的构造函数

秦俊发
2023-03-14

我正在使用一个使用React框架的JavaScript遗留项目。我们定义了一些React组件,我想在一个完全不同的TypeScript React项目中重新使用。

JS React组件在controls.jsx文件中定义,如下所示:

export class MyComponent extends React.Component {
  render() {
    return <h1>Hi from MyComponent! Message provided: {this.props.message}</h1>;
  }
}

在我的TypeScript React项目中,我试图这样使用它:

import * as React from "react";
import * as ReactDOM from "react-dom";
import { MyComponent } from "../JavaScriptProject/controls";

ReactDOM.render(
  <MyComponent message="some nice message"/>,
    document.getElementById("documents-tree")
);

错误消息显示:

JSX元素类型MyComponent不是JSX元素的构造函数。类型'MyComponent'缺少来自类型'ElementClass'的以下属性:上下文、setState、forceUpdate、props和2more.ts(2605)JSX元素类不支持属性,因为它没有'props'property.ts(2607)

我已经尝试过这个问题中描述的自定义打字文件的解决方案,但它没有改变任何东西。

我知道JS组件有一些TypeScript所需的强类型属性,但是在我的Tconfig中。json我将allowJs设置为true:

{
  "compilerOptions": {
    "allowJs": true,
    "baseUrl": ".",
    "experimentalDecorators": true,
    "jsx": "react",
    "noEmitOnError": true,
    "outDir": "lib",
    "sourceMap": true,
    "target": "es5",
    "lib": [
      "es2015",
      "dom"
    ]
  },
  "exclude": [
    "node_modules",
    "dist",
    "lib",
    "lib-amd"
  ]
}

所以我希望它能起作用。。。

多谢你的帮忙

共有3个答案

莫飞翮
2023-03-14

在我看来,你有两个选择:

  1. 您可以在名为controls.t.dscontrols.jsx目录中提供声明文件。

这种选择有两种方式。最简单的方法就是导出名为MyComponent的函数:

export function MyComponent(): any;

第二种方法是导出模拟组件类结构的变量:

interface Element {
    render(): any;
    context: any;
    setState: any;
    forceUpdate: any;
    props: any;
    state: any;
    refs: any;
}

interface MyComponent extends Element {}

export var MyComponent: {
    new(): MyComponent;
}
import React from 'react';
import {MyComponent as _MyComponent} from '../project-a/Controls';

interface MyComponent extends React.Component {}

const MyComponent = (_MyComponent as any) as {
    new(): MyComponent;
};

export {MyComponent};

然后在要使用MyComponent的文件中,您可以从新文件导入它。

这些都是非常糟糕的解决方案,但我相信这是唯一的解决方案,因为TypeScript不允许您定义与项目相关的模块:

declare module "../project/Controls" {

}

希望这有帮助。

尹承业
2023-03-14

以下是我在示例应用程序中使用的供您参考的配置。

tsconfig。json

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react"
  },
  "include": [
    "src"
  ]
}

包裹json

{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.4.0",
    "@testing-library/user-event": "^7.1.2",
    "@types/jest": "^24.0.23",
    "@types/node": "^12.12.18",
    "@types/react": "^16.9.16",
    "@types/react-dom": "^16.9.4",
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "react-scripts": "3.3.0",
    "typescript": "^3.7.3"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

我没有使用webpack。

梁池暝
2023-03-14

您应该将allowSyntheticDefaultImports设置为true,因为React不会导出默认值。

(来源:https://github.com/facebook/react/blob/master/packages/react/index.js)

{
  "compilerOptions": {
    "allowJs": true,
    "baseUrl": ".",
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true, // turn on allowSyntheticDefaultImports
    "jsx": "react",
    "noEmitOnError": true,
    "outDir": "lib",
    "sourceMap": true,
    "target": "es5",
    "lib": [
      "es2015",
      "dom"
    ]
  },
  "exclude": [
    "node_modules",
    "dist",
    "lib",
    "lib-amd"
  ]
}

此外,您应该添加组件道具的形状。例如,在您的代码中:

export class MyComponent extends React.Component<{ message: string }> { ...
 类似资料:
  • 我想调用ReactJS HOC来包装JSX周围的工具提示。 呼叫应能如下所示: 因此,我创建了此函数: 电话: 它说: 函数作为React子函数无效。如果返回组件而不是从渲染返回组件,可能会发生这种情况。或者你想调用这个函数而不是返回它 如何解决?

  • 我正在尝试创建可以在本质上重用的表组件。根据从父组件通过道具传递给它的数据,它可以包含任意数量的列。 为了实现这一点,我创建了如下单独的函数来填充JSX元素。 :它将列名传递作为父字符串数组的道具。 :这将填充每行的body和TableRow。它将调用函数,该函数将返回要推入方法中的JSX元素数组。 :此方法使用中迭代行对象的每个属性,创建TableCell元素,并将其推送到数组中,返回理想情况下

  • 问题内容: React世界中令人沮丧的时间…我需要能够根据某些条件创建标记。例如,我收到一系列物品。我需要检查这些项目,并且基于条件,我需要生成不同的标记。例如,我有一个接收项目数组的函数: 问题是,我不能简单地将单个标记添加到数组中,因为react由于某种原因不喜欢它,而我最终只会得到乱码显示。 有什么主意我该怎么做? 问题答案: 您的解决方案应如下所示: JSX不是HTML,因此无法分多个步骤

  • 问题内容: 我写了一些代码: 我收到一个错误: JSX元素类型没有任何构造或调用签名 这是什么意思? 问题答案: 这是 构造函数 和 实例 之间的混淆。 请记住,在React中编写组件时: 您可以通过以下方式使用它: 您 不会 以这种方式使用它: 在第一个示例中,我们传递了组件的 构造函数 。这是正确的用法。在第二个例子中,我们绕过一个 实例 的。这是不正确的,并且将在运行时失败,并显示诸如“对象

  • 我看到了在JSX中声明元素的两种不同方式。 第一种情况如下所示。 但我也看到了以下元素声明。 这两个元素都可以传递给ReactDOM。render()作为它们的第一个参数。 但这两种语法之间到底有什么区别呢?

  • 问题内容: 我正在我的应用程序中使用React / JSX来完成我想要的,Lodash。 我需要根据条件重复元素一定次数。我该怎么办? 这是元素: 我将其分配为: 因此,在这种情况下,我需要重复元素时间。使用Lodash的程序应该是什么? 问题答案: 干得好: 您可能想要向每个元素添加键,以便React不会抱怨缺少key属性: 有关的更多信息,请参见此处:https : //lodash.com/