TypeScriptを使用したReactコンポーネントのデフォルトプロパティ値


153

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...'.

デフォルトのプロパティ値を使用するにはどうすればよいですか?私の会社が使用する多くのJSコンポーネントはそれらに依存しており、それらを使用しないことは選択肢ではありません。


static defaultProps正しい。そのコードを投稿できますか?
アーロンBeall 2016年

回答:


327

クラスコンポーネントを持つデフォルトの小道具

使用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" } />

ご了承ください:

TypeScript 2.1から3.0まで

TypeScript 3.0が実装される前のコンパイラサポートは、defaultProps引き続き使用でき、実行時にReactで100%動作しましたが、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がの明示的なサポートを追加した主な理由の1つですdefaultProps

TypeScript 2.1以前

これは同じように機能しPartialますが、タイプはありません。省略してPartial<>、必要なすべての小道具のデフォルト値を提供するか(これらのデフォルトが使用されない場合でも)、または明示的なタイプアノテーションを完全に省略します。

機能コンポーネントを持つデフォルトの小道具

あなたは使用することができdefaultProps、同様の機能をコンポーネントに、しかし、あなたはにあなたの関数を入力する必要がFunctionComponentStatelessComponent@types/reactバージョンの前に16.7.2活字体が知っているように)インターフェイスdefaultProps機能に:

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

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

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

はTS 2.1以降ですでにパーシャルとして指定されているPartial<PageProps>ため、どこでも使用する必要はありませんFunctionComponent.defaultProps

別の優れた代替策(これは私が使用する方法です)は、propsパラメーターを分解してデフォルト値を直接割り当てる方法です。

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

その後、あなたはまったく必要ありませんdefaultProps!あなたがいる場合があるので注意してください提供defaultProps常に明示的に渡します反応するので、機能部品にそれがデフォルトのパラメータ値よりも優先されますdefaultProps(パラメータは未定義されることはありませんので、このように、デフォルトのパラメータが使用されることはありません。)あなたが使用したいので値を両方ではなくどちらか一方。


2
エラーは<PageComponent>foo小道具を通過せずにどこかで使用しているように聞こえます。foo?: stringインターフェースで使用して、オプションにすることができます。
アーロンBeall 2016年

1
@Aaronしかし、defaultPropsはPagePropsインターフェースを実装していないため、tscはコンパイルエラーをスローします。すべてのインターフェイスプロパティをオプションにする(悪い)か、すべての必須フィールドにもデフォルト値を指定する(不要なボイラープレート)か、defaultPropsでタイプを指定しないようにする必要があります。
パメラス

1
@adrianmoisaデフォルトの小道具ですか?はい、動作しますが、構文は異なります...コンピュータに戻ったときに、例を回答に追加します...
Aaron Beall

1
@AdrianMoisa s関数コンポーネントの例で更新
Aaron Beall

1
@Jaredはい、すべて(コンパイラとReactランタイム)が正しく動作するためには、public static defaultPropsまたはstatic defaultPropspublicデフォルト)である必要があります。実行時に存在しないprivate static defaultPropsためprivate、実行時に機能する可能性publicがありますが、コンパイラは正しく機能しません。
Aaron Beall 2018年

18

Typescript 2.1+では、インターフェースプロパティをオプションにする代わりに、Partial <T>を使用します。

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

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

6

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ます。


正解です。どのように処理することができます:export interface Props { name?: string;}名前はオプションの小道具ですか?私は続けますTS2532 Object is possibly 'undefined'
Fydo 2018

@Fydoは、オプションのプロップundefinedの一種の自動デフォルト値なので、オプションのプロップにデフォルト値を設定する必要はありません。undefinedときどき明示的な値として渡すことができるようにしたいが、別のデフォルト値を持っていますか?export interface Props {name: string | undefined;}代わりに試しましたか?試したことはありません。アイデアです。
CorayThan 2018

追加すること?は、追加することと同じ|undefinedです。オプションで小道具を渡し、defaultPropsそのケースを処理させたい。これはTS3ではまだ可能ではないようです。いつ設定さname!れるかわからないので、恐ろしい構文を使用します。とにかく、ありがとう!undefineddefaultProps
Fydo 2018

1
これが正しい答えなので、賛成です!また、この新機能ともう少し説明を入れて、私の受け入れられた回答(歴史の本になり始めています)を更新しました。:)
Aaron Beall

5

デフォルト値を必要とするオプションの小道具を持っている人のために。ここにクレジット:)

interface Props {
  firstName: string;
  lastName?: string;
}

interface DefaultProps {
  lastName: string;
}

type PropsWithDefaults = Props & DefaultProps;

export class User extends React.Component<Props> {
  public static defaultProps: DefaultProps = {
    lastName: 'None',
  }

  public render () {
    const { firstName, lastName } = this.props as PropsWithDefaults;

    return (
      <div>{firstName} {lastName}</div>
    )
  }
}

3

承認された回答に関する@pamelusのコメントから:

すべてのインターフェースプロパティをオプションにする(悪い)か、すべての必須フィールドにもデフォルト値を指定する(不要なボイラープレート)か、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"
    };

0

機能コンポーネントについては、私はむしろprops議論を続けたいので、これが私の解決策です:

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

// IMPORTANT!, defaultProps is of type {bar: number} rather than Partial<Props>!
const defaultProps = {
  bar: 1
}


// externalProps is of type Props
const FooComponent = exposedProps => {
  // props works like type Required<Props> now!
  const props = Object.assign(defaultProps, exposedProps);

  return ...
}

FooComponent.defaultProps = defaultProps;

0

機能部品

実際には、機能コンポーネントのベストプラクティスは以下のとおりです。サンプルのSpinnerコンポーネントを作成します。

import React from 'react';
import { ActivityIndicator } from 'react-native';
import { colors } from 'helpers/theme';
import type { FC } from 'types';

interface SpinnerProps {
  color?: string;
  size?: 'small' | 'large' | 1 | 0;
  animating?: boolean;
  hidesWhenStopped?: boolean;
}

const Spinner: FC<SpinnerProps> = ({
  color,
  size,
  animating,
  hidesWhenStopped,
}) => (
  <ActivityIndicator
    color={color}
    size={size}
    animating={animating}
    hidesWhenStopped={hidesWhenStopped}
  />
);

Spinner.defaultProps = {
  animating: true,
  color: colors.primary,
  hidesWhenStopped: true,
  size: 'small',
};

export default Spinner;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.