1. ホーム
  2. javascript

[解決済み] JSX.ElementとReactNodeとReactElementの使い分けは?

2022-03-22 07:33:23

質問

現在、ReactアプリケーションをTypeScriptに移行しているところです。これまでのところ、これはかなりうまくいっているのですが、私は、私の render 関数、特に私の関数型コンポーネントにおいてです。

私はこれまでずっと JSX.Element を返り値として使用することができますが、コンポーネントが ではなく は何もレンダリングしない、つまり null というのは null は有効な値ではありません。 JSX.Element . これが私の旅の始まりでした。ネットで検索してみると ReactNode を含むもので、代わりに null といったことが起こり得ます。

しかし、関数型コンポーネントを作成する際、TypeScriptは以下のような文句を言います。 ReactNode という型があります。ここでもいろいろ調べてみると、関数型コンポーネントには ReactElement 代わりに しかし、そうすると、互換性の問題はなくなるのだが、今度はTypeScriptが再び null は有効な値ではありません。

長くなりましたが、3点ほど質問させてください。

  1. とはどのような違いがあるのでしょうか? JSX.Element , ReactNodeReactElement ?
  2. なぜ render クラスコンポーネントのメソッドが返す ReactNode を返しますが、機能コンポーネントは ReactElement ?
  3. に関して、どのように解決すればよいのでしょうか? null ?

解決方法は?

<ブロッククオート

JSX.Element、ReactNode、ReactElementの違いは何ですか?

ReactElementは、型とプロップを持つオブジェクトです。

 type Key = string | number

 interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
    type: T;
    props: P;
    key: Key | null;
}

ReactNode は、ReactElement、ReactFragment、文字列、数値、ReactNode の配列、null、undefined、boolean のいずれかです。

type ReactText = string | number;
type ReactChild = ReactElement | ReactText;

interface ReactNodeArray extends Array<ReactNode> {}
type ReactFragment = {} | ReactNodeArray;

type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;

JSX.ElementはReactElementで、propsは汎用型、typeはanyです。様々なライブラリが独自の方法でJSXを実装できるため、JSXはグローバルな名前空間であり、ライブラリによって設定されますが、Reactではこのように設定されます。

declare global {
  namespace JSX {
    interface Element extends React.ReactElement<any, any> { }
  }
}

例によって。

 <p> // <- ReactElement = JSX.Element
   <Custom> // <- ReactElement = JSX.Element
     {true && "test"} // <- ReactNode
  </Custom>
 </p>

クラスコンポーネントのレンダーメソッドはReactNodeを返しますが、関数コンポーネントはReactElementを返すのはなぜですか?

確かに、これらは異なるものを返します。 Component が返す。

 render(): ReactNode;

そして、関数は、"ステートレス・コンポーネント"です。

 interface StatelessComponent<P = {}> {
    (props: P & { children?: ReactNode }, context?: any): ReactElement | null;
    // ... doesn't matter
}

これは、実は 歴史的な理由 .

nullに関して、どのように解決すればよいのでしょうか?

のように入力します。 ReactElement | null reactと同じように。あるいはTypescriptに型を推論させる。

<サブ 型のソース