Значение свойства по умолчанию в компоненте React с использованием TypeScript



Я не могу понять, как установить значения свойств по умолчанию для моих компонентов с помощью 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>
);
}
}


и когда я пытаюсь использовать компонент такой:



ReactDOM.render(<PageComponent />, document.getElementById("page"));


я получаю сообщение об ошибке говорящее собственность foo отсутствует. Я хочу использовать значение по умолчанию. Я также пытался использовать static defaultProps = ... внутри компонента, но это не имело никакого эффекта, как я подозревал.



src/typescript/main.tsx(8,17): error TS2324: Property 'foo' is missing in type 'IntrinsicAttributes & IntrinsicClassAttributes<PageComponent> & PageProps & { children?: ReactEle...'.


как я могу использовать значения свойств по умолчанию? Много Javascript компоненты, которые использует моя компания, полагаются на них, и не использовать их-это не выбор.

975   4  

4 ответов:

реквизит по умолчанию с компонентом класса

используя static defaultProps - это правильно. Вы также должны использовать интерфейсы, а не классы, для реквизитов и состояния и отмечать свои необязательные свойства с помощью ?.

обновление для TypeScript 2.1: теперь, когда TS поддерживает частичное типов это хорошая идея, чтобы использовать Partial<Props> аннотация для defaultProps так что вы можете предоставить значения по умолчанию только для ваших дополнительных реквизитов без TS жалуюсь на отсутствие необходимых реквизитов на вашем defaultProps.

вот пример:

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

(это работало до машинописного текста 2.1, опуская Partial<> и предоставление значений по умолчанию для всех необходимых реквизитов, даже если вы действительно просто хотите значения по умолчанию для дополнительных реквизитов.)

проблема с strictNullChecks:

если вы используете strictNullChecks затем пометить опору как необязательную с ? изменит свой тип на T | undefined, что приведет к компилятору ошибка Object is possibly undefined если вы попытаетесь что-нибудь с ним сделать, т. е. this.props.foo.<something>. На данный момент (TS 2.8) вы должны либо использовать ! ненулевое утверждение (ex this.props.foo!.toLowerCase()), или тип-охранник (ex this.props.foo && this.props.foo.toLowerCase()), или абстрагироваться от реквизита по умолчанию с компонентом более высокого порядка (см. "реквизит по умолчанию" в этой статье). У меня зарегистрировал проблему с TypeScript об этом и DefintelyTyped уже был вопрос об этом. Поток не имеет этой проблемы.

обновление: теперь он находится на дорожная карта на июль 2018 года будет исправлено!

реквизит по умолчанию с Функциональные Компоненты Без Гражданства

можно использовать defaultProps на компонентах функции, а также, но вы должны ввести свою функцию в StatelessComponent интерфейс, так что TypeScript знает о defaultProps функции:

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

const PageComponent: StatelessComponent<PageProps> = (props) => {
  return (
    <span>Hello, {props.foo}, {props.bar}</span>
  );
};

PageComponent.defaultProps = {
  foo: "default"
};

обратите внимание, что вы не должны использовать Partial<PageProps> потому что StatelessComponent.defaultProps is указанный в качестве частичной в ТС 2.1+.

еще одна хорошая альтернатива (это то, что я использую), чтобы уничтожить ваш props параметры и назначить значения по умолчанию непосредственно:

const PageComponent: StatelessComponent<PageProps> = ({foo = "default", bar}) => {
  return (
    <span>Hello, {foo}, {bar}</span>
  );
};

тогда вам не нужен defaultProps на всех! Знайте, что если вы do обеспечить defaultProps на компоненте функции он будет иметь приоритет над значениями параметров по умолчанию, потому что React всегда будет явно передавать defaultProps значения (так что параметров не определено, таким образом, параметр по умолчанию не используется.) Таким образом, вы будете использовать один или другой, а не оба.

С Typescript 2.1+, используйте Частичное вместо того, чтобы делать дополнительный свойств интерфейса.

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

public static defaultProps: Partial<Props> = {
    a: true
};

из комментария @pamelus на принятый ответ:

вы либо должны сделать все свойства интерфейс (БАД) или укажите значение по умолчанию также для всех обязательных полей (ненужных boilerplate) или избегайте указания типа на defaultProps.

на самом деле вы можете использовать Typescript в интерфейс наследования. Полученный код только немного более подробный.

interface OptionalGoogleAdsProps {
    format?: string;
    className?: string;
    style?: any;
    scriptSrc?: string
}

interface GoogleAdsProps extends OptionalGoogleAdsProps {
    client: string;
    slot: string;
}


/**
 * Inspired by https://github.com/wonism/react-google-ads/blob/master/src/google-ads.js
 */
export default class GoogleAds extends React.Component<GoogleAdsProps, void> {
    public static defaultProps: OptionalGoogleAdsProps = {
        format: "auto",
        style: { display: 'block' },
        scriptSrc: "//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"
    };

С 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 />

обратите внимание, что для этого вам нужна более новая версия @types/react чем 16.4.6. Он работает с 16.4.11.

Comments

    Ничего не найдено.