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
を使用することは正しいです。小道具と状態のために、クラスではなくインタフェースも使うべきです。
更新2018/12/1:TypeScriptにより型が改善されました - defaultProps
に関連するチェックは時間の経過とともに変わります。古い使用法や問題に至るまでの最新かつ最大の使用法についてお読みください
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
)としてnotとマークされていません。オプションとしてマークすることはそれがundefined
であることを意味しますが、実際にはundefined
はデフォルト値を提供するので決して実際にはdefaultProps
になることはありません。それはどのように似ていると考えてください あなたはオプションとして、またはデフォルト値で、関数パラメータをマークすることができます、しかし両方ともコールが値を指定する必要がないことを意味します 。 TypeScript 3.0以降ではdefaultProps
も同じように扱われます。これはReactユーザーにとっては本当に素晴らしいことです。defaultProps
には明示的な型注釈はありません。その型は、どのJSX属性が必要かを判断するために、コンパイラによって推測され使用されます。 defaultProps
をPageProps
のサブセットと確実に一致させるためにdefaultProps: Pick<PageProps, "foo">
を使用できます。この警告に関する詳細は ここで説明 です。@types/react
バージョン16.4.11
が必要です。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
となり、undefined
を削除するにはnull以外のアサーション(つまりthis.props.foo!
)またはタイプガード(すなわちif (this.props.foo) ...
)が必要になります。デフォルトのprop値が実際には未定義になることはないことを意味するので、これは厄介です。しかしTSはこのフローを理解していませんでした。これが、TS 3.0がdefaultProps
の明示的なサポートを追加した主な理由の1つです。これは同じように機能しますが、Partial
型はありませんので、Partial<>
を省略し、必要なすべての小道具にデフォルト値を指定するか、明示的な型注釈を完全に省略します。
関数コンポーネントにもdefaultProps
を使用できますが、TypeScriptが関数のStatelessComponent
を認識できるように、FunctionComponent
(@types/react
version 16.7.2
+の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>
はTS 2.1+ではすでにパーシャルとして指定されているので、どこにでもStatelessComponent.defaultProps
を使用する必要はありません。
もう一つのいい方法(これは私が使っているものです)はあなたのprops
パラメータを分解してデフォルト値を直接割り当てることです:
const PageComponent: StatelessComponent<PageProps> = ({foo = "default", bar}) => {
return (
<span>Hello, {foo}, {bar}</span>
);
};
それならdefaultProps
はまったく必要ありません。 Reactは常にdefaultProps
の値を明示的に渡すので、関数コンポーネントでdoを指定すると(defaultProps
を指定した場合は優先されます。したがって、デフォルトのパラメータは使用されません。)両方を使用するのではなく、どちらか一方を使用します。
TypeScript 2.1以降では、インターフェイスプロパティをオプションにする代わりにPartial <T>を使用してください。
export interface Props {
obj: Model,
a: boolean
b: boolean
}
public static defaultProps: Partial<Props> = {
a: true
};
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
で動作します。
受け入れられた答えの@pamelusによるコメントから:
すべてのインターフェースプロパティをオプション(無効)にするか、すべての必須フィールドにもデフォルト値を指定する(不要な定型句)か、defaultPropsにtypeを指定しないようにする必要があります。
実際にはTypeScriptの interface inheritance を使うことができます。結果のコードはもう少し冗長です。
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"
};
デフォルト値を必要とするオプションの小道具を持っている人のために。 ここでクレジット:)
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>
)
}
}