本文介绍了使用TypeScript在React组件中的默认属性值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道如何使用Typescript为我的组件设置默认属性值.

I can't figure out how to set default property values for my components using Typescript.

这是源代码:

class PageState
{
}

export class PageProps
{
    foo: string = "bar";
}

export class PageComponent extends React.Component<PageProps, PageState>
{
    public render(): JSX.Element
    {
        return (
            <span>Hello, world</span>
        );
    }
}

当我尝试使用这样的组件时:

And when I try to use the component like this:

ReactDOM.render(<PageComponent />, document.getElementById("page"));

我收到一条错误消息,指出缺少属性foo.我想使用默认值.我也曾尝试在组件内部使用static defaultProps = ...,但是我怀疑它没有任何作用.

I get an error saying property foo is missing. I want to use the default value. I've also tried to use static defaultProps = ... inside the component, but it had no effect as I suspected.

src/typescript/main.tsx(8,17): error TS2324: Property 'foo' is missing in type 'IntrinsicAttributes & IntrinsicClassAttributes<PageComponent> & PageProps & { children?: ReactEle...'.

如何使用默认属性值?我公司使用的许多JS组件都依赖于它们,而不选择不使用它们.

How can I use default property values? Many JS components my company uses rely on them and not using them is not a choice.

推荐答案

带有类组件的默认道具

使用static defaultProps是正确的.您还应该使用接口(而不是类)作为道具和状态.

Default props with class component

Using static defaultProps is correct. You should also be using interfaces, not classes, for the props and state.

更新2018/12/1 :随着时间的推移,TypeScript改进了与defaultProps相关的类型检查.继续阅读以获取最新和最佳用法,直到较旧的用法和问题为止.

Update 2018/12/1: TypeScript has improved the type-checking related to defaultProps over time. Read on for latest and greatest usage down to older usages and issues.

TypeScript特别是添加了对defaultProps 的支持,以使类型检查按预期进行.示例:

TypeScript specifically added support for defaultProps to make type-checking work how you'd expect. Example:

interface PageProps {
  foo: string;
  bar: string;
}

export class PageComponent extends React.Component<PageProps, {}> {
    public static defaultProps = {
        foo: "default"
    };

    public render(): JSX.Element {
        return (
            <span>Hello, { this.props.foo.toUpperCase() }</span>
        );
    }
}

可以在不传递foo属性的情况下进行渲染和编译:

Which can be rendered and compile without passing a foo attribute:

<PageComponent bar={ "hello" } />

请注意:

  • foo is not marked optional (ie foo?: string) even though it's not required as a JSX attribute. Marking as optional would mean that it could be undefined, but in fact it never will be undefined because defaultProps provides a default value. Think of it similar to how you can mark a function parameter optional, or with a default value, but not both, yet both mean the call doesn't need to specify a value. TypeScript 3.0+ treats defaultProps in a similar way, which is really cool for React users!
  • The defaultProps has no explicit type annotation. Its type is inferred and used by the compiler to determine which JSX attributes are required. You could use defaultProps: Pick<PageProps, "foo"> to ensure defaultProps matches a sub-set of PageProps. More on this caveat is explained here.
  • This requires @types/react version 16.4.11 to work properly.

在TypeScript 3.0实现对defaultProps的编译器支持之前,您仍然可以使用它,并且它在运行时可与React一起工作100%,但由于TypeScript在检查JSX属性时仅考虑了props,因此您必须将props标记为?的默认值是可选的.示例:

Before TypeScript 3.0 implemented compiler support for defaultProps you could still make use of it, and it worked 100% with React at runtime, but since TypeScript only considered props when checking for JSX attributes you'd have to mark props that have defaults as optional with ?. Example:

interface PageProps {
    foo?: string;
    bar: number;
}

export class PageComponent extends React.Component<PageProps, {}> {
    public static defaultProps: Partial<PageProps> = {
        foo: "default"
    };

    public render(): JSX.Element {
        return (
            <span>Hello, world</span>
        );
    }
}

请注意:

  • Partial<>注释defaultProps是个好主意,以便对您的道具进行类型检查,但是您不必为每个必需的属性都提供默认值,这是没有意义的,因为必需的属性应该永远不需要默认值.
  • 使用strictNullChecks时,this.props.foo的值将为possibly undefined,并且需要非空声明(即this.props.foo!)或类型保护(即if (this.props.foo) ...)来删除undefined.这很烦人,因为默认的prop值意味着它实际上永远不会被定义,但是TS不能理解这一流程.这是TS 3.0添加了对defaultProps的显式支持的主要原因之一.
  • It's a good idea to annotate defaultProps with Partial<> so that it type-checks against your props, but you don't have to supply every required property with a default value, which makes no sense since required properties should never need a default.
  • When using strictNullChecks the value of this.props.foo will be possibly undefined and require a non-null assertion (ie this.props.foo!) or type-guard (ie if (this.props.foo) ...) to remove undefined. This is annoying since the default prop value means it actually will never be undefined, but TS didn't understand this flow. That's one of the main reasons TS 3.0 added explicit support for defaultProps.

这工作原理相同,但是您没有Partial类型,因此只需忽略Partial<>,或者为所有必需的道具提供默认值(即使永远不会使用这些默认值),或者完全忽略显式类型注释

This works the same but you don't have Partial types, so just omit Partial<> and either supply default values for all required props (even though those defaults will never be used) or omit the explicit type annotation completely.

您也可以在功能组件上使用defaultProps,但是必须在FunctionComponent(版本16.7.2之前的@types/react中的StatelessComponent)界面上键入函数,以便TypeScript知道defaultProps在功能上:

You can use defaultProps on function components as well, but you have to type your function to the FunctionComponent (StatelessComponent in @types/react before version 16.7.2) interface so that TypeScript knows about defaultProps on the function:

interface PageProps {
  foo?: string;
  bar: number;
}

const PageComponent: FunctionComponent<PageProps> = (props) => {
  return (
    <span>Hello, {props.foo}, {props.bar}</span>
  );
};

PageComponent.defaultProps = {
  foo: "default"
};

请注意,您不必在任何地方使用Partial<PageProps>,因为在TS 2.1+中已经将FunctionComponent.defaultProps指定为部分.

Note that you don't have to use Partial<PageProps> anywhere because FunctionComponent.defaultProps is already specified as a partial in TS 2.1+.

另一种不错的选择(这是我使用的方法)是破坏您的props参数并直接分配默认值:

Another nice alternative (this is what I use) is to destructure your props parameters and assign default values directly:

const PageComponent: FunctionComponent<PageProps> = ({foo = "default", bar}) => {
  return (
    <span>Hello, {foo}, {bar}</span>
  );
};

那么您根本不需要defaultProps!请注意,如果您在功能组件上 do 提供defaultProps,它将优先于默认参数值,因为React始终会显式传递defaultProps值(因此参数绝不会是未定义的,因此默认参数是从不使用.)因此,您可以使用其中一个,而不能同时使用.

Then you don't need the defaultProps at all! Be aware that if you do provide defaultProps on a function component it will take precedence over default parameter values, because React will always explicitly pass the defaultProps values (so the parameters are never undefined, thus the default parameter is never used.) So you'd use one or the other, not both.

这篇关于使用TypeScript在React组件中的默认属性值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-13 04:39