我正在使用一个使用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"
]
}
所以我希望它能起作用。。。
多谢你的帮忙
在我看来,你有两个选择:
controls.t.ds
的controls.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" {
}
希望这有帮助。
以下是我在示例应用程序中使用的供您参考的配置。
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。
您应该将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/