# 汎用的なコンポーネントを作成しよう【CSS 編】
繰り返し登場する UI をコンポーネント化して再利用性を高めるアプローチは最近のフロントエンド開発では多用されますが、css の使い方を考えておかないと「あれ?このコンポーネント、汎用的に見えて全然使いまわせない...」など、いざという時に使い回しづらいコンポーネントが出来上がってしまいます
親子に依存関係が存在するとこうしたコンポーネントが生まれやすいため、よく見かけるコンポーネント間の依存関係について考えてみましょう!
# 課題 1
## 課題 1-1
以下の「ReusableButton」はサービスの至る所で利用されることを想定した汎用コンポーネントです。
https://codesandbox.io/s/sad-davinci-51xe3?file=/src/styles.css
実はこのコンポーネントの css には、コンポーネントを再利用しにくくしてしまう問題が潜んでいます。
このコンポーネントの css に潜んでいる問題を一つ教えてください。なぜこのような css の書き方をすると再利用しづらいコンポーネントになってしまうのでしょうか?
💡margin を子が決めていると、他の親が使うときに困りそうですね・・・? そもそも「margin」のように、周囲のコンポーネントとの距離を決めることはこのコンポーネントの責務なのでしょうか?
## 課題 1-2
以下の「Sidemenu」「MainContent」は、画面を左右に分割したレイアウトを実現するためのコンポーネントです。
https://codesandbox.io/s/great-margulis-ir96j?file=/src/App.js
このコンポーネントの css に潜んでいる問題を一つ教えてください。なぜこのような css の書き方をすると再利用しづらいコンポーネントになってしまうのでしょうか?
💡仮に親である App が `display:flex` ではなくなった時、どうなってしまうでしょうか・・・?
このように親の状態に子が依存したコンポーネントを作ってしまうと、何がいけないのでしょうか?
Sidemenu と MainContent コンポーネントをより再利用しやすいよう css を書き直してみてください。
💡「左右の分割されたレイアウトにする」という責務を親だけが担うようにしてみるのはどうでしょうか?
## 課題 1-3
ここまでの課題で紹介したパターンは全て「親からの呼ばれ方に依存するような汎用コンポーネントを作らないこと」を伝えるための題材でした。今度は「親からの要求に柔軟に対応する汎用コンポーネント」を見てみましょう。
以下の「CustomButton」は親から className を受け取ることで自由に色を変えられるようにしています。例えば「CustomBlueButton」は CustomButton に対して color: blue を指定した class を渡すことで、デフォルトのボタンを拡張しています。
https://codesandbox.io/s/aged-glade-6grnuk
このコンポーネントは className を props として受け取ることができますが、これは好ましい実装かどうかチームで話し合ってみてください。
# 課題 2
「フォーカスされている時に見た目が変わる Input コンポーネントを実装してくれ」と言われました。
こんなコンポーネントを実装してみました、このコンポーネントについて考えてみましょう
```tsx
import { useState } from 'react';
import styles from './Input.module.css';
export const Input = () => {
const [isFocused, setIsFocused] = useState(false);
return (
<input
className={`${styles.input} ${isFocused ? styles.focused : ''}`}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
/>
);
};
```
## 課題 2-1
isFocused という状態で focus の有無を検知し、isFocused が真の場合に特定のスタイルを当てるという実装のようです。
この実装の問題点についてチームで話し合ってみてください!
💡「制御コンポーネント」「非制御コンポーネント」というキーワードについて調べてみましょう
## 課題 2-2
JS を使用せずに「フォーカスされている時に見た目が変わる Input コンポーネント」を実装してみましょう。
💡[CSSにはDOMの状態に応じてスタイルを指定できる機能](https://developer.mozilla.org/ja/docs/Web/CSS/CSS_selectors) がありそうです
## 課題 2-3
HTML/CSS だけでコンポーネントを実装することにはどんな利点があるでしょうか?
チームで話し合ってみましょう!