Реагировать с помощью TypeScript - определять defaultProps в функции без сохранения

Я использую 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?

Как упоминается в реагировать на документы:

(...) Они являются чистыми функциональными преобразованиями их ввода, с нулевым шаблонный. Тем не менее, вы все равно можете указать .propTypes и .defaultProps, установив их как свойства функции, так же, как вы должны установить их в классе ES6. (...)

это должно быть легко:

CenterBox.defaultProps = {
    minHeight: 250
}

Но этот код генерирует ошибку TSLint: error TS2339: Property 'defaultProps' does not exist on type '(props: CenterBoxProps) => Element'.

Итак, как я могу правильно определить defaultProps в моем выше стеке (React + TypeScript)?

Ответ 1

Через 2 часа поиска решения... работает.

Если вы хотите определить deufaultProps, ваша строка, определяющая вашу функцию, должна выглядеть так:

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

Затем вы можете определить реквизиты, например:

CenterBox.defaultProps = { someProp: true }

Обратите внимание, что React.SFC является псевдонимом для React.StatelessComponent.

Я надеюсь, что этот вопрос (и ответ) поможет кому-то. Убедитесь, что вы установили новейшие титры React.

Ответ 2

И здесь, как это работает для функций с сохранением состояния, если другие наткнуться на это. Ключ объявляет 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;
};

Ответ 3

Я считаю, что лучший способ, чем описанный в документации по React, - это просто использовать аргументы Javascript/Typescript по умолчанию.

Здесь ответ здесь: fooobar.com/questions/1654464/... но для удобства приведу пример:

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 знать, что вам не нужно предоставлять реквизит, а также что он никогда не будет "неопределенным" внутри вашего компонента.

Ответ 5

Ввод реквизитов по умолчанию в компонент функции с помощью 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')
);

Ответ 6

Вы можете поместить это в свой компонент

static defaultProps: any;