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 を用意することで何かと混線することもなく、過不足なくコンポーネント内部のコンポーネントに外から値を渡せるようになります。