[英]JSX element type 'string' is not a constructor function for JSX elements. Typescript
[英]Using JS React component in TypeScript: JSX element type 'MyComponent' is not a constructor function for JSX elements
我正在處理一個使用 React 框架的 JavaScript 遺留項目。 我們定義了一些 React 組件,我想在一個完全不同的 TypeScript React 項目中重用它們。
JS React 組件在 control.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”類型中的以下屬性:context、setState、forceUpdate、props 和另外 2 個。ts(2605) JSX 元素類不支持屬性,因為它沒有“props”屬性。ts (2607)
我已經嘗試過使用此問題中描述的自定義類型文件的解決方案,但它沒有任何改變。
我知道 JS 組件缺少 TypeScript 所需的一些強類型屬性,但是在我的 tsconfig.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"
]
}
所以我希望它應該工作......
謝謝你的幫助
您應該將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 }> { ...
以下是我在示例應用程序中使用的配置供您參考。
配置文件
{
"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。
在我看來,你有兩個選擇:
controls.jsx
相同的目錄中提供一個名為controls.t.ds
的聲明文件。 此選項有兩種處理方式。 最簡單的就是導出一個名為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" {
}
希望這可以幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.