与TypeScript反应 - 在无状态函数中定义defaultProps

时间:2016-05-16 19:46:05

标签: reactjs typescript

我正在使用React和TypeScript,并且我已经创建了无状态功能。为了便于阅读,我已从示例中删除了无用的代码。

interface CenterBoxProps extends React.Props<CenterBoxProps> {
    minHeight?: number;
}

export const CenterBox = (props: CenterBoxProps) => {
    const minHeight = props.minHeight || 250;
    const style = {
        minHeight: minHeight
    };
    return <div style={style}>Example div</div>;
};

一切都很棒,这段代码工作正常。但是我的问题是:如何为defaultProps组件定义CenterBox

正如react docs中提到的那样:

  

(...)它们是输入的纯函数变换,为零   样板。但是,您仍可以指定.propTypes和    .defaultProps 将它们设置为函数的属性,就像   你可以在ES6课上设置它们。 (...)

应该很容易:

CenterBox.defaultProps = {
    minHeight: 250
}

但是此代码生成TSLint错误:error TS2339: Property 'defaultProps' does not exist on type '(props: CenterBoxProps) => Element'.

再次说明:如何在上面的堆栈中正确定义defaultProps(React + TypeScript)?

7 个答案:

答案 0 :(得分:21)

寻找解决方案2小时后...... 它的工作

如果要定义deufaultProps,则函数定义行应如下所示:

export const CenterBox: React.SFC<CenterBoxProps> = props => {
    (...)
};

然后你可以定义像:

这样的道具
CenterBox.defaultProps = { someProp: true }

请注意,React.SFCReact.StatelessComponent的别名。

我希望这个问题(和答案)可以帮助别人。确保您已安装最新的React类型。

答案 1 :(得分:8)

以下是有状态函数的工作原理,以防其他人偶然发现这种情况。 关键是将 defaultProps 声明为静态变量。

interface IBoxProps extends React.Props<IBoxProps> {
    x?: number;
    y?: number;
    height?: number;
    width?: number;
}

interface IBoxState {
    visible?: boolean;
}

export default class DrawBox extends React.Component<IBoxProps, IBoxState> {
    static defaultProps: IBoxProps;

    constructor(props: IBoxProps) {
        super(props);
    }
    ...
}

DrawBox.defaultProps = {
    x=0;
    y=0;
    height=10;
    weight=10;
};

答案 2 :(得分:2)

我相信比React文档中描述的更好的方法是简单地使用Javascript / Typescript默认参数。

这里有一个答案:https://stackoverflow.com/a/54569933/484190,但是为了方便起见,下面是一个示例:

import React, { FC } from "react";

interface CompProps {
  x?: number;
  y?: number;
}

const Comp: FC<CompProps> = ({ x = 10, y = 20 }) => {
  return <div>{x}, {y}</div>;
}

export default Comp;

这将使Typescript知道您不必提供道具,并且永远不会在组件内部对其进行“不确定”

答案 3 :(得分:1)

对于自 React 16.7.0 起的功能组件,“ React.SFC”类型已被弃用,而以“ React.FC”代替。

示例

type TFuncComp = React.FC<{ text: string }>

const FuncComp: TFuncComp = props => <strong>{props.text}</strong>

FuncComp.defaultProps = { text: 'Empty Text' }

Deprecation Warning in Source

FC (FunctionalComponent) Type in Source

答案 4 :(得分:1)

使用React.FC在功能组件中键入默认道具会导致错误的类型错误:

   type Props = {
     required: string,
   } & typeof defaultProps;

   const defaultProps = {
     optDefault: 'optDefault'
   };

   const MyComponent: React.FC<Props> = (props: Props) => (
     <ul>
       <li>required: {props.required}</li>
       <li>optDefault: {props.optDefault}</li>
     </ul>
   )
   MyComponent.defaultProps = defaultProps;


   ReactDOM.render(
     <div>
       <MyComponent
         required='required'
         optDefault='over written'
       />
       <MyComponent   /* type error  <---- false type error */
         required='required'
       />
     </div>,
     document.getElementById('app')
   );

错误:

[tsserver 2741] Property 'optDefault' is missing in type '{ required: string; }' but required in type '{ optDefault: string; }'. [E]

提出的另一种解决方案是使用Javascript自己的默认函数参数:

type Props = {
  required: string,
  optDefault?: string
}

const MyComponent:  React.FC<Props> = ({
  required,
  optDefault='default'
}: Props) => (
  <ul>
    <li>required: {required}</li>
    <li>optDefault: {optDefault}</li>
  </ul>
)

ReactDOM.render(
  <div>
    <MyComponent
      required='required'
      optDefault='over written'
    />
    <MyComponent
      required='required'
    />
  </div>,
  document.getElementById('app')
);

但是此解决方案的问题在于,如果您忘记提供默认值,则会导致运行时错误:

const MyComponent: React.FC<Props> = ({
  required,
  optDefault //='optDefault' //<--- if you forgot to provide default
}: Props) => (
  <ul>
    <li>required: {required}</li>
    <li>optDefault: {optDefault}</li> {/* <-- result in bug */}
  </ul>
)

更好的解决方案是根本不使用React.FC,只需依靠Typescript类型推断即可:

type Props = {
  required: string,
} & typeof defaultProps;

const defaultProps = {
  optDefault: 'optDefault'
};

const MyComponent = (props: Props) => (
  <ul>
    <li>required: {props.required}</li>
    <li>optDefault: {props.optDefault}</li>
  </ul>
)
MyComponent.defaultProps = defaultProps


ReactDOM.render(
  <div>
    <MyComponent
      required='required'
      optDefault='over written'
    />
    <MyComponent
      required='required'
    />
  </div>,
  document.getElementById('app')
);

答案 5 :(得分:0)

您可以将其放入组件中

static defaultProps: any;

答案 6 :(得分:-1)

对我来说,最简单的方法是直接在defaultProps中定义(部分)默认值:

export default class TSError extends React.Component<ITSErrorProps, {}> {
  private static defaultProps: Partial<ITSErrorProps> = {
    fullPage: true,
    controlClick: true,
    doubleClick: true
  };

...

}