如何在TypeScript中将子级与React无状态功能组件一起使用?


84

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

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参数中将提供香草函数。

所以问题是我们应该如何在TypeScript的无状态功能组件中使用子代?

我可以回到的旧方法MyProps extends React.Props,但是该Props接口被标记为已弃用,并且Props.ref据我所知,无状态组件不具有或不支持。

所以我可以children手动定义道具:

interface MyProps {
  children?: React.ReactNode;
}

第一:是ReactNode正确的类型吗?

第二:我必须将子级写为可选(?),否则消费者会认为这children应该是组件()的属性<MyStatelessComponent children={} />如果未提供值,则会引发错误。

好像我缺少什么。谁能说清楚我的最后一个示例是否是在React中对子级使用无状态功能组件的方法?

Answers:


82

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<>类型:

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

我在此处添加的内容是将组件的返回类型设置为React.StatelessComponenttype。

对于具有自己的自定义道具(例如MyProps界面)的组件:

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

现在,props已经有了children属性以及来自MyProps接口的属性。

我在打字稿版本2.0.7中检查了这一点

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


谢谢!看来我使用的是不支持此功能的旧版本...我想是时候该忍痛使用TS 2.0了@types
Aaron Beall

2
React.StatelessComponent/React.SFC已弃用。建议改为参考React.FunctionComponent
亚历山大·卡切夫

请注意,如果您有通用组件,则此方法不起作用
FunkeyFlo19年

92

您可以将React.PropsWithChildren<P>type用于道具:

interface MyProps { }

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

0

您可以使用

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

0

比较简单的答案:使用ReactNode

interface MyProps {
  children?: React.ReactNode
}

Ifchildren是否可选(即是否具有?)取决于您的组件。在?最简洁的方式来表达,所以没有什么不妥。

关于历史:最初询问时,这不一定是正确的答案:仅ReactNode在2017年3月通过该请求请求在当前形式中添加了该类型,但是今天几乎所有阅读此类型的人都应该使用足够现代的React版本。

最后,关于传递children为“属性”(在React术语中,将其传递为“ prop”而不是属性):可以,但是在大多数情况下,传递JSX子级时读取效果更好:

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

阅读比

<MyComponent children={<p>This is part of the children.</p>} />
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.