Ответ 1
Упор по умолчанию с компонентом класса
Использование static 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
не помечен как необязательный (т.е.foo?: string
), даже если он не требуется в качестве атрибута JSX. Пометка как необязательная означает, что это может бытьundefined
, но на самом деле это никогда не будетundefined
, потому чтоdefaultProps
предоставляет значение по умолчанию. Подумайте об этом подобно тому, как вы можете пометить параметр функции как необязательный, или значением по умолчанию, но не обоими, но оба означают, что вызову не нужно указывать значение. TypeScript 3. 0+ обрабатываетdefaultProps
аналогичным образом, что действительно здорово для пользователей React!defaultProps
не имеет явной аннотации типа. Его тип выводится и используется компилятором, чтобы определить, какие атрибуты JSX требуются. Вы можете использоватьdefaultProps: Pick<PageProps, "foo">
, чтобы убедиться, чтоdefaultProps
соответствует подмножествуPageProps
. Подробнее об этом предупреждении объясняется здесь.- Для этого требуется
@types/react
версия16.4.11
для правильной работы.
Для TypeScript 2.1 до 3.0
До того, как в TypeScript 3.0 была реализована поддержка компилятора для defaultProps
, вы все еще могли использовать его, и он работал на 100% с React во время выполнения, но поскольку TypeScript учитывал только реквизиты при проверке атрибутов JSX, вы должны были пометить реквизиты со значениями по умолчанию как опционально с ?
. Пример:
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>
);
}
}
Обратите внимание:
- Хорошей идеей будет аннотировать
defaultProps
с помощьюPartial<>
, чтобы он проверял тип по вашим реквизитам, но вам не нужно указывать каждому обязательному свойству значение по умолчанию, что не имеет смысла, поскольку для обязательных свойств никогда не требуется по умолчанию. - При использовании
strictNullChecks
значениеthis.props.foo
будетpossibly undefined
и потребует ненулевого подтверждения (т.е.this.props.foo!
) или защиты типа (т.е.if (this.props.foo) ...
), чтобы удалитьundefined
. Это раздражает, так как значение prop по умолчанию означает, что оно фактически никогда не будет неопределенным, но TS не понимает этот поток. Это одна из главных причин, по которой в TS 3.0 добавлена явная поддержкаdefaultProps
.
До TypeScript 2.1
Это работает так же, но у вас нет типов Partial
, поэтому просто опустите Partial<>
и либо предоставьте значения по умолчанию для всех требуемых реквизитов (даже если эти значения по умолчанию никогда не будут использоваться), либо полностью пропустите явную аннотацию типов.
Упор по умолчанию с функциональными компонентами
Вы также можете использовать defaultProps
на компонентах функций, но вы должны ввести свою функцию в интерфейс FunctionComponent
(StatelessComponent
в @types/react
до версии 16.7.2
), чтобы 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+.
Еще одна хорошая альтернатива (это то, что я использую) - это деструктурировать ваши параметры props
и напрямую назначить значения по умолчанию:
const PageComponent: FunctionComponent<PageProps> = ({foo = "default", bar}) => {
return (
<span>Hello, {foo}, {bar}</span>
);
};
Тогда тебе вообще не нужен defaultProps
! Помните, что если вы предоставите defaultProps
для компонента функции, он будет иметь приоритет над значениями параметров по умолчанию, поскольку React всегда будет явно передавать значения defaultProps
(поэтому параметры никогда не определяются, поэтому параметр по умолчанию никогда не используется. ) Таким образом, вы будете использовать один или другой, а не оба.