reactjs - TypeScriptでReactのステートレス関数コンポーネントでchildrenを使用する方法
TypeScriptをReactと一緒に使う場合、コンパイラがすべてのReactコンポーネントのプロパティが children を持てることを認識するために、React.Props を拡張する必要はなくなりました:
interface MyProps { }
class MyComponent extends React.Component<MyProps, {}> {
public render(): JSX.Element {
return <div>{this.props.children}</div>;
}
}
しかし、ステートレス関数コンポーネントについてはそうではないようです。
const MyStatelessComponent = (props: MyProps) => {
return (
<div>{props.children}</div>
);
};
コンパイルエラーを発生させます:
エラー:(102, 17) TS2339: 型 'MyProps' にはプロパティ 'children' が存在しません。
おそらくこれは、コンパイラが通常の関数に props 引数で children が渡されることを知る方法が本当にないからだと思います。
では、問題はTypeScriptでステートレス関数コンポーネントに子要素をどのように使うべきかということですか?
私は古い方法の MyProps extends React.Props に戻ることもできますが、Props インターフェースは非推奨とマークされており、ステートレスコンポーネントには Props.ref が存在せず、サポートもされていないと理解しています。
だから、私は children プロパティを手動で定義することができました:
interface MyProps {
children?: React.ReactNode;
}
まず:ReactNodeは正しい型ですか?
二つ目:children はオプション(?)として書かなければなりません。そうしないと、利用者は children がコンポーネントの 属性(<MyStatelessComponent children={} />)であるべきだと考え、値が提供されていないとエラーが発生します。
何か見落としているようです。誰か、私の最後の例がReactで子コンポーネントを持つステートレス関数コンポーネントの使い方として正しいかどうかを教えてもらえますか?
回答 #1
あなたはプロパティに React.PropsWithChildren<P> 型を使用できます:
interface MyProps { }
function MyComponent(props: React.PropsWithChildren<MyProps>) {
return <div>{props.children}</div>;
}
回答 #2
React 16.8 更新: React 16.8 以降、React.SFC と React.StatelessComponent の名前は非推奨になりました。実際には、それらは React.FunctionComponent 型、または略して React.FC のエイリアスとして機能します。
それでも同じように使います:
const MyStatelessComponent : React.FunctionComponent<MyProps> = props =>
<div>
<p>{props.propInMyProps}</p>
<p>{props.children}</p>
</div>
React 16.8以前(古いバージョン):
とりあえず、次のように React.StatelessComponent<> 型を使用できます:
const MyStatelessComponent : React.StatelessComponent<{}> = props =>
<div>{props.children}</div>
そこで私が追加したのは、コンポーネントの戻り値の型をReact.StatelessComponent型に設定することです。
独自のカスタムプロパティ(例えば MyProps インターフェース)を持つコンポーネントの場合:
const MyStatelessComponent : React.StatelessComponent<MyProps> = props =>
<div>
<p>{props.propInMyProps}</p>
<p>{props.children}</p>
</div>
さて、props は MyProps インターフェースのものに加えて、children プロパティも持つようになりました。
私はこれを TypeScript バージョン 2.0.7 で確認しました
さらに、簡潔にするために React.StatelessComponent の代わりに React.SFC を使用することができます。
回答 #3
簡単な答え:ReactNodeを使用します:
interface MyProps {
children?: React.ReactNode
}
children がオプションかどうか(つまり ? があるかどうか)は、あなたのコンポーネント次第です。? はそれを表現する最も簡潔な方法なので、何も問題はありません。
歴史について: これは元々質問された時点では必ずしも正しい答えではありませんでした: 型 ReactNode はこのプルリクエストによって、ほぼ現在の形で2017年3月に追加されましたが、今日これを読んでいるほとんどの人は十分に新しいバージョンのReactを使っているはずです。
最後に、children を「属性」として渡すことについて(React の用語では「属性」ではなく「prop」として渡すことを指します):可能ではありますが、ほとんどの場合は JSX の children を渡す方が読みやすいです。
<MyComponent>
<p>This is part of the children.</p>
</MyComponent>
より読みやすい
<MyComponent children={<p>This is part of the children.</p>} />
