React with TypeScript - define defaultProps in stateless function

前端 未结 7 1541
梦如初夏
梦如初夏 2021-02-01 04:56

I\'m using React with TypeScript and I\'ve created stateless function. I\'ve removed useless code from the example for readability.

interface CenterBoxProps exte         


        
相关标签:
7条回答
  • 2021-02-01 05:12

    Typing default props in function component with React.FC can result in false type error:

       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')
       );
    

    error:

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

    Another solution proposed is to use Javascript's own default function parameters:

    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')
    );
    

    But the problem with this solution is that if you forgot to provide default, a run time bug will result:

    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>
    )
    

    A better solution is not using React.FC at all, simply rely on Typescript type inference:

    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')
    );
    
    0 讨论(0)
  • 2021-02-01 05:13

    You can put this inside your component

    static defaultProps: any;
    
    0 讨论(0)
  • 2021-02-01 05:16

    After 2 hours of looking for solution... it's working.

    If you want to define defaultProps, your arrow function should look like:

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

    Then you can define props like:

    CenterBox.defaultProps = { someProp: true }
    

    Note that React.SFC is alias for React.StatelessComponent.

    I hope that this question (and answer) help somebody. Make sure that you have installed newest React typings.

    0 讨论(0)
  • 2021-02-01 05:16

    I believe a better way than described in the React docs is simply to use Javascript / Typescript default arguments.

    There's an answer here: https://stackoverflow.com/a/54569933/484190 but for convenience, here's an example:

    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;
    

    This will allow Typescript to know that you don't have to provide the prop, and also that it will never be "undefined" inside your component

    0 讨论(0)
  • 2021-02-01 05:25

    For Functional Components as of React 16.7.0 the 'React.SFC' type is being deprecated in favour of 'React.FC'.

    Example

    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

    0 讨论(0)
  • 2021-02-01 05:27

    And here's how it works for stateful functions in case others stumble on this. The key is declaring defaultProps as a static variable.

    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;
    };
    
    0 讨论(0)
提交回复
热议问题