如何在 TypeScript 中使用带有 React 无状态功能组件的子组件?

Posted

技术标签:

【中文标题】如何在 TypeScript 中使用带有 React 无状态功能组件的子组件?【英文标题】:How to use children with React Stateless Functional Component in TypeScript? 【发布时间】:2017-04-06 12:20:33 【问题描述】:

将 TypeScript 与 React 一起使用,我们不再需要扩展 React.Props 以使编译器知道所有 React 组件道具都可以有子代:

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: 类型上不存在属性 'children' '我的道具'。

我猜这是因为编译器真的无法知道在 props 参数中将给出一个原版函数 children

那么问题是我们应该如何在 TypeScript 的无状态函数组件中使用子组件?

我可以回到MyProps extends React.Props 的旧方式,但Props 接口是marked as deprecated,据我了解,无状态组件没有或不支持Props.ref

所以我可以手动定义 children 属性:

interface MyProps 
  children?: React.ReactNode;

首先:ReactNode 是正确的类型吗?

第二:我必须将 children 写为可选 (?) 否则消费者会认为 children 应该是组件 (&lt;MyStatelessComponent children= /&gt;) 的一个属性,并引发如果没有提供值,则会出错。

我好像错过了什么。谁能提供一些关于我的最后一个示例是否是在 React 中将无状态功能组件与子级一起使用的方法?

【问题讨论】:

【参考方案1】:

您可以使用React.PropsWithChildren&lt;P&gt; 类型作为您的道具:

interface MyProps  

function MyComponent(props: React.PropsWithChildren<MyProps>) 
  return <div>props.children</div>;

【讨论】:

【参考方案2】:

React 16.8 更新: 从 React 16.8 开始,名称 React.SFCReact.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&lt;&gt; 类型,如:

const MyStatelessComponent : React.StatelessComponent<> = props =>
    <div>props.children</div>

我在那里添加的是将组件的返回类型设置为React.StatelessComponent 类型。

对于具有您自己的自定义 props 的组件(如 MyProps 接口):

const MyStatelessComponent : React.StatelessComponent<MyProps> = props =>
    <div>
        <p>props.propInMyProps</p>
        <p>props.children</p>
    </div>

现在,props 获得了children 属性以及来自MyProps 接口的属性。

我在 typescript 版本 2.0.7 中检查了这一点

此外,为简洁起见,您可以使用React.SFC 代替React.StatelessComponent

【讨论】:

谢谢!看来我正在使用不支持此功能的旧版本的类型......我想是时候硬着头皮使用 TS 2.0 和 @types React.StatelessComponent / React.SFC 已弃用。建议改为参考React.FunctionComponent 请注意,如果您有通用组件,则此方法不起作用【参考方案3】:

更简单的答案:使用ReactNode

interface MyProps 
  children?: React.ReactNode

children 是否可选(即是否有?)取决于您的组件。 ? 是表达这一点最简洁的方式,所以没有错。

关于历史:当最初被问到时,这不一定是正确的答案:ReactNode 类型(几乎)是在 2017 年 3 月以当前形式添加的 by this pull request,但今天几乎每个阅读本文的人都应该 使用足够现代的 React 版本。

最后,关于将children 作为“属性”传递(在 React 术语中,将其作为“属性”而不是属性传递):这是可能的,但在大多数情况下,传递 JSX 子级时会更好:

<MyComponent>
  <p>This is part of the children.</p>
</MyComponent>

比阅读更容易

<MyComponent children=<p>This is part of the children.</p> />

【讨论】:

【参考方案4】:

您可以将子组件添加到组件中,如果它连接到您所需要的容器。

const MyComponent = ( 
   children  
) => 
  return <div>children</div>


【讨论】:

这是一个 TypeScript 问题。【参考方案5】:

你可以使用

interface YourProps  
const yourComponent: React.SFC<YourProps> = props => 

【讨论】:

React.SFC 已弃用

以上是关于如何在 TypeScript 中使用带有 React 无状态功能组件的子组件?的主要内容,如果未能解决你的问题,请参考以下文章

如何像在 babelrc 中创建依赖别名一样在 typescript 中创建类型别名?

使用 create-react-app 和 Typescript 时如何在构建时加载 .md 文件?

如何在带有 Typescript 的视图中使用 Vue 单文件组件?

如何在带有 Typescript 项目的 React Native 中使用 AWS Amplify?

如何在 TypeScript 中使用带有 React 无状态功能组件的子组件?

如何在带有 typescript 项目的 react js 中使用 .env 文件?