React はコンポーネントベースで UI(ユーザインタフェース)を定義する機能を持ったライブラリです。自分の場合 React を web 上で使うことが多いです。
React – ユーザインターフェース構築のための JavaScript ライブラリ
React は多くのユーザに使われており、React のフレームワーク、コンポーネント集といったライブラリも多くあります。これらは便利なのですが、しばしば要件を満たすために機能が少ない場合があります。その場合、用意されたコンポーネントを拡張したコンポーネントを用意することで使いまわしやすく、十分な機能を持ったコンポーネントを定義することになります。この半自家製コンポーネントは時折、機能が足りなくなり、機能をつぎ足すことが必要になります。このつぎ足す際に元々のライブラリのコンポーネントではできていたことができなくなると不便です。このため機能を損なわず、拡張もしっかり行えるコンポーネントの書き方があると便利です。その書き方が楽であればなお良しです。
自分がよく行い、他の方の書いたライブラリ等でもしばしば見かけるコンポーネントの拡張パターンが次です。
type SomeComponentProps = {
label: string; // コンポーネントを拡張した時のオリジナル props
TextField1Props: TextFieldProps; // 元々の型定義をそのまま参照。元々は渡せた props が渡せなくなることを防ぎます
TextField2Props: TextFieldProps; // 元々の型定義をそのまま参照。複数のコンポーネントの集合なので & で型を増やすのではなく、プロパティを増やす
};
const SomeComponent = (props: SomeComponentProps) => {
// ライブラリのコンポーネントの props のデフォルトを設定する
// ちょっとタグやコンポーネントを増やして使いやすくするなどなどの拡張をします
return (
<React.Fragment>
<label>{{props.label}}</label>
<TextField
error={!!errors[props.name]}
helperText={errors[props.name]?.message || props.helperText}
InputProps={{
...props.TextField1Props.InputProps,
onChange: handleChange
}}
{...props.TextField1Props}
/>
{/* 元々の props 定義と等しい定義の渡された props をスプレッド演算子で展開して渡します */}
<TextField {...props.TextField2Props} />
</React.Fragment>
);
}
元々の要素、あるいはコンポーネントの props すべてを受け持つ Object の props を用意することで何かと混線することもなく、過不足なくコンポーネント内部のコンポーネントに外から値を渡せるようになります。