# 汎用的なコンポーネントを作成しよう【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 だけでコンポーネントを実装することにはどんな利点があるでしょうか? チームで話し合ってみましょう!