TypeScriptでのJS Reactコンポーネントの使用:JSX要素タイプ 'MyComponent'はJSX要素のコンストラクター関数ではありません


8

私は、Reactフレームワークを使用するJavaScriptレガシープロジェクトを使用しています。まったく異なるTypeScript Reactプロジェクトで再利用したい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'の次のプロパティがありません:context、setState、forceUpdate、props、および2 more.ts(2605)JSX要素クラスは 'props'プロパティがないため、属性をサポートしていません。 (2607)

この質問で説明されているカスタムタイピングファイルを使用してソリューションをすでに試しましたが、何も変わりません。

JSコンポーネントにはTypeScriptに必要な強く型付けされたプロパティがいくつか不足していることを理解していますが、私のtsconfig.jsonではallowJstrueに設定しています

{
  "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"
  ]
}

それがうまくいくことを望みました...

ご協力いただきありがとうございます


これらのソリューションを試しましたか-> github.com/DefinitelyTyped/DefinitelyTyped/issues/21242
Mihai T

試しましたが、何の役にも立ちません...私は糸を使わないので、無関係なものはほとんどありませんでした。他の人はまったく役に立たない...
DawidSibiński19年

問題なく動作します。typescriptアプリを作成し、srcにcontrols.jsxファイルを追加しました。
ディープ

うーん...多分それはいくつかのnpmパッケージの問題ですか?またはそれらのバージョン?tsconfig.json、package.json、そしておそらくwebpack.config.jsを共有できますか?
DawidSibiński19年

これは、reactとreact-domタイピングが一致していないように聞こえます。あなたのpackage-lockとpackage.jsonを共有できますか?その長さのため、pastebin / gistにパッケージロックを配置する必要があるかもしれません。
ダンパントリー

回答:


1

Reactはデフォルトをエクスポートしないので、をオンallowSyntheticDefaultImportsにする必要trueがあります。

(ソース: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 }> { ...

1
答えてくれてありがとう。設定allowSyntheticDefaultImportstrueの変更は何も、私はまだ同じエラーを取得しています。コンポーネントプロップの形状を追加できません。.jsxファイルで定義されているため、次のエラーが発生します。「「タイプ引数」は.tsファイルでのみ使用できます。ts(8011)」
DawidSibiński

0

これが、サンプルアプリケーションで使用している参照の構成です。

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"
  ]
}

package.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を使用していません。


私はあなたの設定を取っても助けにはなりません...:/
DawidSibińskiDec

0

私の見方では、2つのオプションがあります。

  1. controls.jsxnamed と同じディレクトリに宣言ファイルを提供できますcontrols.t.ds

このオプションには、2つの方法があります。最も簡単なのは、次の名前の関数をエクスポートすることですMyComponent

export function MyComponent(): any;

2つ目は、コンポーネントのクラス構造を模倣する変数をエクスポートすることです。

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;
}
  1. 2番目のオプションは、コンポーネントをインポートし、タイプ定義を使用して再エクスポートすることです。このファイルはプロジェクト内のどこかに含まれます:
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" {

}

お役に立てれば。


私はオプション2を試してみましたが、私はさらに追加して、この余分なファイルを宣言したmessagestringコンポーネントに種類を(MyComponent extends React.Component<{ message: string }>新しいファイルからこのコンポーネントをインポートするときにVSのコードは私にすべてのエラーを与えるものではありません。しかし、私はまだ、コンパイルエラーを取得しています新しいファイル:Module not found: Error: Can't resolve '../../../../JS_TS_Project/Scripts/application/controls'
DawidSibiński19年

@DawidSibińskiどのパッケージャを使用していますか?メトロ、バベル、WebPack?
カイル

私はwebpackを使用しています
DawidSibińskiJan

@DawidSibińskiJS_TS_Projectをインクルード解決に含めるようにWebpackに指示する必要があると思います。このSOの回答を参照してください:stackoverflow.com/a/54257787/701263
カイル

@Kyleに感謝しますが、それでも機能しません...私は少しあきらめました。結局、別のTSコンポーネントを使用しました。ただし、この問題は未解決で興味深いものです。これらのソリューションのいずれかが機能したとしても、これは両方のモジュール/プロジェクトを緊密に結合しており、信頼性が高く再利用可能なソリューションにはほど遠いものです。
DawidSibiński
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.