使用 TypeScript 的 React 组件中的默认属性值 [英] Default property value in React component using TypeScript
问题描述
我不知道如何使用 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.
推荐答案
类组件的默认 props
使用 static defaultProps
是正确的.您还应该为 props 和 state 使用接口,而不是类.
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
是 not 标记为可选的(即foo?: string
),即使它不是 JSX 属性所必需的.标记为可选意味着它可以是undefined
,但实际上它永远不会是undefined
,因为defaultProps
提供了一个默认值.想想它类似于 您可以将函数参数标记为可选,或使用默认值,但不能同时使用两者,但这都意味着调用不需要指定值.TypeScript 3.0+ 以类似的方式对待defaultProps
,这对 React 用户来说真的很酷!defaultProps
没有明确的类型注释.它的类型由编译器推断和使用,以确定需要哪些 JSX 属性.您可以使用defaultProps: Pick
来确保defaultProps
匹配PageProps
的子集.关于这个警告的更多信息是 在这里解释.- 这需要
@types/react
版本16.4.11
才能正常工作.
foo
is not marked optional (iefoo?: string
) even though it's not required as a JSX attribute. Marking as optional would mean that it could beundefined
, but in fact it never will beundefined
becausedefaultProps
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+ treatsdefaultProps
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 usedefaultProps: Pick<PageProps, "foo">
to ensuredefaultProps
matches a sub-set ofPageProps
. More on this caveat is explained here. - This requires
@types/react
version16.4.11
to work properly.
在 TypeScript 3.0 实现对 defaultProps
的编译器支持之前,您仍然可以使用它,并且它在运行时 100% 与 React 一起工作,但是由于 TypeScript 在检查 JSX 属性时只考虑了道具必须使用 ?
将具有默认值的道具标记为可选.示例:
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
的值将是可能未定义
并且需要一个非空断言(即this.props.foo!
) 或类型保护(即if (this.props.foo) ...
) 删除undefined
.这很烦人,因为默认的 prop 值意味着它实际上永远不会是未定义的,但是 TS 不理解这个流程.这是 TS 3.0 明确支持defaultProps
的主要原因之一.
- It's a good idea to annotate
defaultProps
withPartial<>
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 ofthis.props.foo
will bepossibly undefined
and require a non-null assertion (iethis.props.foo!
) or type-guard (ieif (this.props.foo) ...
) to removeundefined
. 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 fordefaultProps
.
这工作相同,但您没有 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
(StatelessComponent
in 版本
) 接口,以便 TypeScript 知道函数上的 16.7.2
之前的 @types/reactdefaultProps
:
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
,因为 FunctionComponent.defaultProps
已在 TS 2.1+ 中指定为部分.
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 组件中的默认属性值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!