Reactjs 使用TypeScript的React组件中的默认属性值

Reactjs 使用TypeScript的React组件中的默认属性值,reactjs,typescript,tsx,Reactjs,Typescript,Tsx,我不知道如何使用Typescript为组件设置默认属性值 这是源代码: class PageState { } export class PageProps { foo: string = "bar"; } export class PageComponent extends React.Component<PageProps, PageState> { public render(): JSX.Element { return (

我不知道如何使用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>
        );
    }
}
如何使用默认属性值?我公司使用的许多JS组件依赖它们,不使用它们不是一个选择。

类组件的默认道具
使用静态默认道具是正确的。对于道具和状态,还应该使用接口,而不是类

更新2018/12/1:随着时间的推移,TypeScript改进了与
defaultProps
相关的类型检查。请继续阅读,了解最新和最大的用法,以及较旧的用法和问题

适用于TypeScript 3.0及以上版本 TypeScript专门用于使类型检查按预期方式工作。例如:

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>
        );
    }
}
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>
        );
    }
}
请注意:

  • foo
    未标记为可选(即
    foo?:string
    ),即使它不是JSX属性所必需的。标记为可选意味着它可以是
    未定义的
    ,但实际上它永远不会是
    未定义的
    ,因为
    defaultProps
    提供了一个默认值。想一想它是怎样的。TypeScript 3.0+以类似的方式处理
    defaultProps
    ,这对React用户来说非常酷
  • defaultProps
    没有显式类型注释。它的类型由编译器推断并用于确定需要哪些JSX属性。您可以使用
    defaultProps:Pick
    确保
    defaultProps
    匹配
    PageProps
    的子集。关于这个警告的更多信息是
  • 这需要
    @types/react
    版本
    16.4.11
    才能正常工作
对于TypeScript 2.1到3.0 在TypeScript 3.0实现对
defaultProps
的编译器支持之前,您仍然可以使用它,并且它在运行时100%与React一起工作,但是由于TypeScript在检查JSX属性时只考虑了props,因此您必须将具有默认值的props标记为可选的
。例如:

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>
        );
    }
}
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
,因为
FunctionComponent.defaultProps
已在TS 2.1+中指定为Partial

另一个不错的选择(这就是我使用的)是分解
props
参数并直接指定默认值:

const PageComponent: FunctionComponent<PageProps> = ({foo = "default", bar}) => {
  return (
    <span>Hello, {foo}, {bar}</span>
  );
};
constpagecomponent:FunctionComponent=({foo=“default”,bar})=>{
返回(
你好,{foo},{bar}
);
};

那么你根本不需要
defaultProps
!请注意,如果在函数组件上提供了
defaultProps
,它将优先于默认参数值,因为React将始终显式传递
defaultProps
值(因此参数永远不会未定义,因此永远不会使用默认参数)。因此,您可以使用其中一个,并非两者都有。

来自@pamelus对公认答案的评论:

您必须将所有接口属性设置为可选(错误)或 还为所有必填字段指定默认值(不必要 或者避免在defaultProps上指定类型

实际上你可以使用Typescript的。生成的代码只是稍微详细一点

界面选项GoogleadProps{
格式?:字符串;
类名?:字符串;
风格?:任何;
scriptSrc?:字符串
}
接口GoogleadProps扩展了可选GoogleadProps{
客户端:字符串;
插槽:字符串;
}
/**
*灵感来自https://github.com/wonism/react-google-ads/blob/master/src/google-ads.js
*/
导出默认类GoogleAds扩展React.Component{
公共静态默认道具:OptionalGoogleAdsProps={
格式:“自动”,
样式:{display:'block'},
scriptSrc://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js
};

对于Typescript 2.1+,请使用部分而不是将界面属性设置为可选

export interface Props {
    obj: Model,
    a: boolean
    b: boolean
}

public static defaultProps: Partial<Props> = {
    a: true
};
导出接口道具{
obj:模型,
a:布尔型
b:布尔型
}
公共静态defaultProps:Partial={
a:是的
};

对于Typescript 3.0,此问题有一个解决方案:

export interface Props {
    name: string;
}

export class Greet extends React.Component<Props> {
    render() {
        const { name } = this.props;
        return <div>Hello ${name.toUpperCase()}!</div>;
    }
    static defaultProps = { name: "world"};
}

// Type-checks! No type assertions needed!
let el = <Greet />
导出接口道具{
名称:字符串;
}
export类扩展React.Component{
render(){
const{name}=this.props;
返回Hello${name.toUpperCase()}!;
}
静态defaultProps={name:“world”};
}
//类型检查!不需要类型断言!
设el=

请注意,要实现此功能,您需要更新版本的
@types/react
而不是
16.4.6
。对于那些拥有需要默认值的可选道具的人,它可以与
16.4.11
配合使用

界面道具{
名字:字符串;
lastName?:字符串;
}
界面默认道具{
lastName:string;
}
键入PropsWithDefaults=Props&DefaultProps;
导出类用户扩展React.Component{
公共静态defaultProps:defaultProps={
姓氏:“无”,
}
公开渲染(){
const{firstName,lastName}=this.props作为PropsWithDefaults;
返回(
{firstName}{lastName}
)
}
}

对于功能组件,我宁愿保留
props
参数,因此下面是我的解决方案:

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

// IMPORTANT!, defaultProps is of type {bar: number} rather than Partial<Props>!
const defaultProps = {
  bar: 1
}


// externalProps is of type Props
const FooComponent = exposedProps => {
  // props works like type Required<Props> now!
  const props = Object.assign(defaultProps, exposedProps);

  return ...
}

FooComponent.defaultProps = defaultProps;
界面道具{
foo:string;
条?:编号;
}
//重要!defaultProps的类型是{bar:number},而不是部分!
const defaultProps={
酒吧:1
}
//外部道具属于道具类型
const FooComponent=exposedProps=>{
//道具就像现在需要的类型一样工作!
const props=Object.assign(defaultProps,exposedProps);
返回。。。
}
FooComponent.defaultProps=defaultProps;
功能部件 实际上,对于功能组件,最佳实践如下所示,我创建了一个示例微调器组件:

从“React”导入React;
从“react native”导入{ActivityIndicator};
从“helpers/theme”导入{colors};
从“类型”导入类型{FC};
界面喷丝头{
颜色?:字符串;
大小?:“小”和“大”1 | 0;
动画制作?:布利亚
export interface Props {
    name: string;
}

export class Greet extends React.Component<Props> {
    render() {
        const { name } = this.props;
        return <div>Hello ${name.toUpperCase()}!</div>;
    }
    static defaultProps = { name: "world"};
}

// Type-checks! No type assertions needed!
let el = <Greet />
interface Props {
  firstName: string;
  lastName?: string;
}

interface DefaultProps {
  lastName: string;
}

type PropsWithDefaults = Props & DefaultProps;

export class User extends React.Component<Props> {
  public static defaultProps: DefaultProps = {
    lastName: 'None',
  }

  public render () {
    const { firstName, lastName } = this.props as PropsWithDefaults;

    return (
      <div>{firstName} {lastName}</div>
    )
  }
}
interface Props {
  foo: string;
  bar?: number; 
}

// IMPORTANT!, defaultProps is of type {bar: number} rather than Partial<Props>!
const defaultProps = {
  bar: 1
}


// externalProps is of type Props
const FooComponent = exposedProps => {
  // props works like type Required<Props> now!
  const props = Object.assign(defaultProps, exposedProps);

  return ...
}

FooComponent.defaultProps = defaultProps;
interface MyProps {
   text: string;
   optionalText?: string;
}

const defaultProps = {
   optionalText = "foo";
}

const MyComponent = (props: MyProps) => {
   props = { ...defaultProps, ...props }
}