# 汎用的なコンポーネントを作成しよう【props編】 前回の課題でコンポーネントを適切な粒度で切り出す方法を学びました。 適切な粒度で切り出したとしても、適切なコンポーネント設計ができないとコンポーネントを使用する場所が変わるたびにそのコンポーネントを何度も変更しなければいけなくなります。 適切なコンポーネント設計についてより詳しく学んで、汎用的かつメンテナンスコストが低いコンポーネントを作れるようになりましょう! # 課題1 以下の仕様を満たすボタンコンポーネントを実装してみてください - `content`というpropsでボタンに表示する内容を切り替えることができる - `color`というpropsでボタンの背景色を青色・緑色・赤色に切り替えることができる - `size`というpropsでボタンの大きさを切り替えることができる - `disabled` というpropsが真の場合はボタンをクリックすることができなくなり、ボタンの背景色が灰色になる - `<任意の名前>` のpropsでボタンをクリックした時にを実行される関数を渡すことができる 💡HTMLの`<button>`タグがあるのにボタンコンポーネントを実装するのは、プロジェクトのいろんな場所で同じスタイルや同じ機能を持ったボタンを実装する手間を省くためであるはずです 。汎用的に使用できるコンポーネントにするために、できるだけHTMLの`<button>`タグに近い動作をしながら上記の仕様を満たせるように実装してみましょう 。 # 課題2 ## 課題2-1 課題1で作ったコンポーネントについて考えてみて、どんな実装が好ましいかチーム話し合ってみてください - `content` というpropsはどんな型にしましたか? - `string` にした場合、ボタンに表示するテキストを変更できるようになりますが文字列以外は表示できなそうです。 - たとえば「Googleでログイン」ボタンを実装したいとき、Googleのアイコンと文字列を渡したくなると思います。 - 解決策の一つとして`children` にした場合、なんでも渡せるようになりますが`<button>`の中に表示しない方が良いものも渡せてしまいます - `color`というpropsはどんな型にしましたか? - `string` にした場合、実際には黄色にならない`color: yellow` を渡せるコンポーネントになってしまいますね - `size`というpropsでボタンの大きさはどのように変更しましたか? - ボタンのwidthやheightを固定して変更する場合、ボタンのテキストが長い場合はボタンからテキストがはみ出してしまうかもしれません - `disabled` というpropsはどのように使用しましたか?その場合見た目を灰色にするにはどう実装すれば良いでしょうか? - HTMLの`<button>`タグはdisabled属性を受け付けているので、propsのdisabledをそのまま渡せそうです - クリックした時に発火する関数にはどんな名前をつけましたか? - 💡イベントハンドラであること + クリックした時に発火する関数であることがわかりやすい名前をつけることができるとよさそうです。 - 「ボタンをクリックした時に特定のInput欄にtextを入力する」という例を考えます。 - 受け取るprops名は自由につけることができるので、クリックした時に起こることがわかりやすいように`setText` というpropsをつけることができそうです。 - しかし、これはあまり良くない命名かもしれません。なぜか理由を考えてみましょう。 ## 課題2-2 課題1で作ったボタンコンポーネントに修正が入ることについて考えてみましょう! あなたは上司から「クリックした時に発火する関数を渡せるようにしてもらったけど、ホバーした時に発火する関数も渡せるようにして欲しいな」と言われました。 単に`onHover` を渡せるようにすれば解決しそうですが、このあと「ごめん、〇〇した時に発火する関数を渡せるようにして欲しいな」と言われるたびにpropsの型を変更 + buttonにpropsを渡すように変更しなくてはいけません。 もっと楽に実装する方法を探してみてください。 💡[すごく便利な型](https://react-typescript-cheatsheet.netlify.app/docs/react-types/componentprops/)がありそうです、これを使えば元々`<button>`に渡せるpropsを1つ1つ自前で定義していく必要がなくなりそうです