默认道具与类组件
使用静态defaultProps是正确的。对于道具和状态,还应该使用接口,而不是类。
2018/12/1更新:随着时间的推移,TypeScript已经改进了与defaultProps相关的类型检查。继续阅读,从最新和最好的用法到较老的用法和问题。
适用于TypeScript 3.0及以上版本
TypeScript特别添加了对defaultProps的支持,以使类型检查按您期望的方式工作。例子:
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属性的情况下进行渲染和编译:
<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 2.1到3.0
在TypeScript 3.0实现编译器对defaultProps的支持之前,你仍然可以使用它,并且它在运行时100%适用于React,但由于TypeScript在检查JSX属性时只考虑props,所以你必须用?标记默认的props为可选。例子:
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>
);
}
}
注意:
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.
在TypeScript 2.1之前
这是相同的工作方式,但您没有Partial类型,因此只需省略Partial<>,并为所有必需的道具提供默认值(即使这些默认值永远不会使用),或者完全省略显式类型注释。
功能组件的默认道具
你也可以在函数组件上使用defaultProps,但是你必须将你的函数输入到FunctionComponent(在16.7.2版本之前@types/react中的StatelessComponent)接口中,这样TypeScript才能知道函数上的defaultProps:
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>,因为FunctionComponent.defaultProps在TS 2.1+中已经被指定为Partial。
另一个不错的选择(这是我使用的)是解构你的props参数,并直接分配默认值:
const PageComponent: FunctionComponent<PageProps> = ({foo = "default", bar}) => {
return (
<span>Hello, {foo}, {bar}</span>
);
};
那么你就根本不需要defaultProps了!请注意,如果你在函数组件上提供了defaultProps,它将优先于默认参数值,因为React总是显式地传递defaultProps值(因此参数永远不会是undefined,因此默认参数永远不会被使用)。所以你只能用其中一个,而不是两个。