見出し画像

HTMLElementを継承してReact Componentを作る方法

Reactのコンポーネントを作成する際、皆さんはどのような方法を使用しているでしょうか?よくあるケースとして、<input>、<select>、<img>などのHTMLタグを継承して独自のコンポーネントを作成することがあります。

ここではその方法をメモしておきます。

export type IProps = TextareaHTMLAttributes<HTMLTextAreaElement> & {
    error: boolean; // デフォルトのTextAreaにerrorプロパティを追加
    border: boolean; // デフォルトのTextAreaにborderプロパティを追加
};

// TextareaHTMLAttributes<HTMLTextAreaElement> &でTextAreaのデフォルトのプロパティを継承している。

デフォルトのHTMLのプロパティを継承するために、PropsにHTMLAttributes<T>のような型をマージすることができます。
これにより、自分が作成したいコンポーネントのPropsにデフォルトのHTMLのプロパティを組み込むことができます。以下はInputコンポーネントの例です。

以下はInputコンポーネントの例です。

InputHTMLAttributes<HTMLInputElement>

interface InputHTMLAttributes<T> extends HTMLAttributes<T> {
 accept?: string;
 alt?: string;
 autoComplete?: string;
 autoFocus?: boolean;
 capture?: boolean | string; // https://www.w3.org/TR/html-media-capture/#the-capture-attribute
 checked?: boolean;
 crossOrigin?: string;
 disabled?: boolean;
 enterKeyHint?: 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send';
 form?: string;
 formAction?: string;
 formEncType?: string;
 formMethod?: string;
 formNoValidate?: boolean;
 formTarget?: string;
 height?: number | string;
 list?: string;
 max?: number | string;
 maxLength?: number;
 min?: number | string;
 minLength?: number;
 multiple?: boolean;
 name?: string;
 pattern?: string;
 placeholder?: string;
 readOnly?: boolean;
 required?: boolean;
 size?: number;
 src?: string;
 step?: number | string;
 type?: string;
 value?: string | ReadonlyArray<string> | number;
 width?: number | string;

 onChange?: ChangeEventHandler<T>;
}

以下にいくつかの例を示します。

// <input />
InputHTMLAttributes<HTMLInputElement>

// <TextArea />
TextareaHTMLAttributes<HTMLTextAreaElement>

// <Select />
SelectHTMLAttributes<HTMLSelectElement>

// <Img />
ImgHTMLAttributes<HTMLImageElement>

これで、デフォルトのHTML要素のプロパティを継承して独自のコンポーネントを作成することができるようになりました。

<Input type={'text'} name={'name'} maxLength={10} error={isBool} border={isBorder} />

これにより、input要素に存在するプロパティの設定だけでなく、独自に追加したプロパティの設定も可能なコンポーネントが作成できるようになりました。

それでは。

いいなと思ったら応援しよう!