【问题标题】:How can I type a React.FC with non-optional `children`?如何键入带有非可选“children”的 React.FC?
【发布时间】:2021-05-04 17:42:38
【问题描述】:

在编写 TypeScript (tsx) 时,我通常使用 React.FC<Props>(或 React.FunctionComponent<Props>)键入我的 React 组件,其中 Props 是我自己的 prop 类型的接口。然后,打字系统会将children? 添加到我的组件所采用的道具列表中。

但这使得children 属性是可选的。

所以我们有React.VFC 用于没有子组件的组件,React.FC 用于具有可选子组件的组件。但是对于具有强制子级的组件,我可以使用什么?

我可以像这样手动完成,但我希望有一种更清洁的方法。

interface ParentFunctionComponent<P = {}> {
  (props: PropsWithMandatoryChildren<P>, context?: any): ReactElement<any, any> | null;
  propTypes?: WeakValidationMap<P>;
  contextTypes?: ValidationMap<any>;
  defaultProps?: Partial<P>;
  displayName?: string;
}

type PropsWithMandatoryChildren<P> = P & { children: ReactNode };

【问题讨论】:

  • 我认为您的意思是 React.VFC 用于定义一个没有子组件的组件(而不是 React.VFS)。我猜这是一个错字,因为没有VFS 类型。我会编辑,但编辑队列已满。

标签: reactjs typescript


【解决方案1】:

将非可选的children 添加到props。

import React from 'react';

export interface Props {
  children: React.ReactNode;
}

const Foo: React.FC<Props> = (props) => {
  return <>{props.children}</>;
};

function Bar() {
  return (
    <>
      {/*
        <Foo />     error
        <Foo></Foo> error
      */}

      <Foo>hello</Foo>

      <Foo>
        <div>foo bar</div>
      </Foo>
    </>
  );
}

【讨论】:

    【解决方案2】:

    如果辅助类型不够用,你总是可以通过编写自己的类型来扩展反应类型:

    在 src 文件夹的某处创建 types.d.ts 文件,

    添加此代码:

    declare module React {
        declare interface FCC<P> {
            (props: P & { children: ReactElement }, context?: any): ReactElement | null;
            propTypes?: WeakValidationMap<P>;
            contextTypes?: ValidationMap<any>;
            defaultProps?: Partial<P>;
            displayName?: string;
        }
    }
    
    

    您可能希望使用一些继承来避免维护定义的其他部分(displayName、propTypes 等)

    【讨论】:

    • 请记住,这些代码会影响整个代码库。它可能会混淆项目中的其他开发人员
    • 甚至,当 React 改变 FunctionComponent 中的某些内容时,它可能会被破坏。但是作者知道使用更安全的东西,比如辅助类型,这就是为什么我提出了这样的解决方案
    • 好的,@Drag13 - 在那种情况下没问题))))我不够专心
    【解决方案3】:

    如果我想要强制子级,我会以这种方式编写函数组件:

    interface IProps {
        title: string;
        children: ReactNode;
    }
    
    export const Section = (props: IProps) => {
        const { title, children } = props;
    
        return (
            ***
        );
    };

    【讨论】:

      猜你喜欢
      • 2022-01-23
      • 1970-01-01
      • 2021-12-26
      • 2022-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多