【问题标题】:How convert class component to functional with function constructor?如何使用函数构造函数将类组件转换为函数式?
【发布时间】:2021-11-08 04:15:26
【问题描述】:

我正在尝试将此类组件转换为函数组件,但我需要该组件具有这些静态属性。

export class InputBox<T extends string|number|undefined = undefined> extends React.Component<IInputBoxProps<T>, IInputBoxState> {
    static displayName = "InputBox";
    static defaultProps: IInputBoxProps<string|number> = {
        disabled: false,
        rightAligned: false,
        id: "",
        keySelectIndex: 0,
    }

... rest of component
}

我试过这段代码:

export const InputBox: React.FunctionComponent<IInputBoxProps<any>> = <T extends string | number | undefined = undefined >(props: IInputBoxProps<T>) => {
    InputBox.displayName = "InputBox";
    InputBox.defaultProps = {
        disabled: false,
        rightAligned: false,
        id: "",
        keySelectIndex: 0,
    }

... rest of component
}

当我运行这段代码时,我收到一个 eslint 错误提示:

FunctionComponent&lt;IInputBox&lt;any&gt;&gt;' is not a constructor function type.

T = any 在这里也不起作用。我知道any 有点让打字稿没用,但我似乎无法绕过这个错误。

如何使用“构造函数类型”键入函数组件,这究竟是什么意思?

类构造函数中的函数构造函数和类构造函数有什么区别? 我应该在函数组件中以不同的方式键入静态道具吗?

【问题讨论】:

  • 我仍然收到 lint 错误。我也没有得到defaultPropsdisplayName 作为智能感知建议?
  • @Kulio 你用的是什么版本的 TS? Aleksey 的示例在 4.4.4 中为我提供了智能感知建议
  • "typescript": "^4.4.4"

标签: reactjs typescript


【解决方案1】:

通用组件

export const InputBox: React.FunctionComponent<IInputBoxProps<any>> = <T ...

这种语法永远不会正常工作,因为您试图在函数本身上设置通用T。泛型的要点是每次调用函数时T 都可以不同。

所以你不能在这里使用React.FunctionComponent 类型。但是你不需要——只需设置道具的类型。

如果您的 eslint 设置使用规则 explicit-module-boundary-names,那么您还需要将返回类型设置为 JSX.Element(或 JSX.Element | null,如果它可能返回 null)。


默认道具

defaultProps 并不真正存在于函数组件 (See discussion here) 上。与其尝试在您的函数组件上设置 defaultProps 属性,不如考虑该属性实际上在做什么以及如何实现该功能。

我会在破坏属性时使用defaultProps 中的值作为默认值来处理这个问题。 (注意:我不确定这里的 T 适用于什么)。

const InputBox = <T extends string | number | undefined = undefined>(
    props: IInputBoxProps<T>
) => {
    const {
        disabled = false,
        rightAligned = false,
        id = "",
        keySelectIndex = 0,
        // ... other props without defaults
    } = props;
...

或内联

const InputBox = <T extends string | number | undefined = undefined>(
    { disabled = false, rightAligned = false, id = "", keySelectIndex = 0, data }: IInputBoxProps<T>
) => {
...

显示名称

displayName 并不是真正需要的,因为推断的显示名称将是函数的名称。它已经是"InputBox"。如果您使用了 option { ignoreTranspilerName: true },您应该只会在此处收到 eslint 错误。

正如您在rule examples 中看到的,您必须首先创建函数,然后将displayName 属性分配给函数。 Aleksey 的评论正确地做到了这一点。

const InputBox = <T extends string | number | undefined = undefined>(
    props: IInputBoxProps<T>
): JSX.Element => {
    /* ... */
}
InputBox.displayName = "InputBox";

【讨论】:

  • 嗯,我明白了。感谢这个非常详细的答案。欣赏!
猜你喜欢
  • 1970-01-01
  • 2021-10-16
  • 2022-11-07
  • 1970-01-01
  • 2018-01-12
  • 2014-06-23
  • 1970-01-01
  • 2021-05-31
  • 1970-01-01
相关资源
最近更新 更多