React共通コンポーネントの作り方完全ガイド!ボタンと入力フォームを再利用しよう
生徒
「Reactでボタンや入力フォームを何度も書くのが面倒です。もっと効率的な方法はありませんか?」
先生
「それなら共通コンポーネントを作るのがおすすめです。一度作ったボタンやフォームを、何度でも使い回せるようになりますよ。」
生徒
「共通コンポーネントって難しそうですね。初心者でも作れますか?」
先生
「大丈夫です!基本的な仕組みを理解すれば、誰でも簡単に作れますよ。それでは、具体的な作り方を見ていきましょう!」
1. 共通コンポーネントとは何か?その仕組みを理解しよう
共通コンポーネントとは、アプリケーション内で何度も使われる部品を、一つのコンポーネントとしてまとめたものです。例えば、お弁当箱を想像してみてください。毎日違うおかずを入れても、お弁当箱そのものは同じですよね。Reactの共通コンポーネントも同じで、外側の形は同じでも、中身のデータを変えることで様々な場面で使えるのです。
ボタンや入力フォームは、ウェブアプリケーションのあらゆる場所で使われます。これらを毎回一から書いていると、コードが長くなり、修正も大変になります。共通コンポーネントを作ることで、一箇所を修正するだけで、使っている全ての場所に変更が反映されるため、とても便利なのです。
共通コンポーネントを作る際には、propsという仕組みを使います。propsは、コンポーネントに外部から情報を渡すための窓口のようなもので、これによって同じコンポーネントでも異なる見た目や動作を実現できます。
2. 基本的な共通ボタンコンポーネントを作ってみよう
まずは、シンプルな共通ボタンコンポーネントを作ってみましょう。以下のコードは、テキストと色を変えられるボタンの例です。
import React from "react";
function Button(props) {
return (
<button
onClick={props.onClick}
style={{
backgroundColor: props.color || "#007bff",
color: "white",
padding: "10px 20px",
border: "none",
borderRadius: "5px",
cursor: "pointer",
fontSize: "16px"
}}
>
{props.text}
</button>
);
}
function App() {
const handleClick = () => {
alert("ボタンがクリックされました!");
};
return (
<div>
<h1>共通ボタンの例</h1>
<Button text="保存する" color="#28a745" onClick={handleClick} />
<Button text="削除する" color="#dc3545" onClick={handleClick} />
<Button text="キャンセル" color="#6c757d" onClick={handleClick} />
</div>
);
}
export default App;
このコードでは、props.textでボタンのテキストを、props.colorで背景色を受け取っています。また、||という記号を使って、色が指定されなかった場合のデフォルト値を設定しています。これにより、色を指定しなくても青色のボタンが表示されます。
3. さらに便利な入力フォームコンポーネントを作成する
次は、入力フォームの共通コンポーネントを作ってみましょう。入力フォームは、ユーザーから情報を受け取るための重要な部品です。ラベルやプレースホルダーを設定できるようにします。
import React, { useState } from "react";
function InputField(props) {
return (
<div style={{ marginBottom: "15px" }}>
<label style={{ display: "block", marginBottom: "5px", fontWeight: "bold" }}>
{props.label}
</label>
<input
type={props.type || "text"}
placeholder={props.placeholder}
value={props.value}
onChange={props.onChange}
style={{
width: "100%",
padding: "8px 12px",
border: "1px solid #ccc",
borderRadius: "4px",
fontSize: "14px"
}}
/>
</div>
);
}
function App() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
return (
<div style={{ padding: "20px", maxWidth: "400px" }}>
<h1>ユーザー登録フォーム</h1>
<InputField
label="お名前"
placeholder="山田太郎"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<InputField
label="メールアドレス"
type="email"
placeholder="example@email.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<p>入力された名前: {name}</p>
<p>入力されたメール: {email}</p>
</div>
);
}
export default App;
ここで使っているuseStateは、コンポーネントの状態を管理するための機能です。stateとは、コンポーネントが持つデータのことで、このデータが変わると画面も自動的に更新されます。onChangeイベントは、入力欄の値が変わるたびに実行される処理で、これによって入力内容を追跡できます。
4. サイズやスタイルを変更できるボタンを作る
共通コンポーネントは、様々なバリエーションに対応できるようにすると、さらに使いやすくなります。サイズを選べるボタンコンポーネントを作ってみましょう。
import React from "react";
function FlexibleButton(props) {
const sizes = {
small: { padding: "5px 10px", fontSize: "12px" },
medium: { padding: "10px 20px", fontSize: "16px" },
large: { padding: "15px 30px", fontSize: "20px" }
};
const currentSize = sizes[props.size] || sizes.medium;
return (
<button
onClick={props.onClick}
disabled={props.disabled}
style={{
backgroundColor: props.disabled ? "#cccccc" : (props.color || "#007bff"),
color: "white",
padding: currentSize.padding,
fontSize: currentSize.fontSize,
border: "none",
borderRadius: "5px",
cursor: props.disabled ? "not-allowed" : "pointer",
margin: "5px"
}}
>
{props.text}
</button>
);
}
function App() {
const handleSubmit = () => {
alert("送信しました!");
};
return (
<div style={{ padding: "20px" }}>
<h1>様々なサイズのボタン</h1>
<FlexibleButton text="小さいボタン" size="small" onClick={handleSubmit} />
<FlexibleButton text="普通のボタン" size="medium" color="#28a745" onClick={handleSubmit} />
<FlexibleButton text="大きいボタン" size="large" color="#ffc107" onClick={handleSubmit} />
<FlexibleButton text="無効なボタン" disabled={true} onClick={handleSubmit} />
</div>
);
}
export default App;
disabled属性は、ボタンを無効化するための機能です。フォームの入力が不完全な場合など、ユーザーにまだ押してほしくないときに使います。また、三項演算子? :を使って、無効かどうかで表示を変えています。
5. バリデーション機能付き入力フォームを作成する
実際のアプリケーションでは、入力内容をチェックする機能が必要です。エラーメッセージを表示できる入力フォームを作ってみましょう。バリデーションとは、入力された値が正しいかどうかを確認する処理のことです。
import React, { useState } from "react";
function ValidatedInput(props) {
return (
<div style={{ marginBottom: "20px" }}>
<label style={{ display: "block", marginBottom: "5px", fontWeight: "bold" }}>
{props.label}
{props.required && <span style={{ color: "red" }}> *</span>}
</label>
<input
type={props.type || "text"}
placeholder={props.placeholder}
value={props.value}
onChange={props.onChange}
style={{
width: "100%",
padding: "8px 12px",
border: props.error ? "2px solid #dc3545" : "1px solid #ccc",
borderRadius: "4px",
fontSize: "14px"
}}
/>
{props.error && (
<p style={{ color: "#dc3545", fontSize: "12px", marginTop: "5px" }}>
{props.error}
</p>
)}
</div>
);
}
function App() {
const [email, setEmail] = useState("");
const [emailError, setEmailError] = useState("");
const handleEmailChange = (e) => {
const value = e.target.value;
setEmail(value);
if (value && !value.includes("@")) {
setEmailError("正しいメールアドレスを入力してください");
} else {
setEmailError("");
}
};
return (
<div style={{ padding: "20px", maxWidth: "400px" }}>
<h1>バリデーション付きフォーム</h1>
<ValidatedInput
label="メールアドレス"
type="email"
placeholder="your@email.com"
value={email}
onChange={handleEmailChange}
error={emailError}
required={true}
/>
</div>
);
}
export default App;
このコンポーネントでは、props.errorの有無によって、入力欄の枠の色を変えています。また、&&という論理演算子を使って、エラーがある場合だけエラーメッセージを表示するようにしています。requiredプロパティで必須項目を示す赤いアスタリスクも表示できます。
6. アイコン付きボタンコンポーネントの作成
見た目が良く、分かりやすいボタンを作るには、アイコンを追加するのが効果的です。アイコンとテキストを組み合わせたボタンコンポーネントを作ってみましょう。
実際のウェブアプリケーションでは、保存ボタンにはフロッピーディスクのアイコン、削除ボタンにはゴミ箱のアイコンなど、視覚的に分かりやすくする工夫がされています。アイコンを使うことで、言語が違うユーザーでも直感的に操作できるようになります。
アイコンを表示する方法はいくつかありますが、絵文字を使う方法が最も簡単です。絵文字は特別なライブラリを読み込まなくても使えるため、初心者の方にもおすすめです。また、アイコンの位置を左右に変えられるようにすると、さらに柔軟性が高まります。
7. 複数の入力タイプに対応したフォームコンポーネント
入力フォームには、テキスト入力だけでなく、パスワード入力、数値入力、日付選択など、様々なタイプがあります。これらすべてに対応できる汎用的なコンポーネントを作ることで、開発効率が大きく向上します。
HTMLのinputタグには、type属性を変えることで様々な入力形式に対応できます。例えば、type="password"にすると入力内容が隠され、type="number"にすると数値専用の入力欄になります。これらを一つのコンポーネントで扱えるようにすると便利です。
また、テキストエリアのような複数行の入力欄も、同じコンポーネントで扱えるようにすると良いでしょう。textareaタグは、長文を入力する際に使われる要素で、お問い合わせフォームのメッセージ欄などでよく使われます。
8. 共通コンポーネントを別ファイルに分ける方法
共通コンポーネントは、別のファイルに保存して管理するのが一般的です。これにより、複数のページやコンポーネントから簡単に呼び出すことができます。例えば、componentsというフォルダを作り、その中にButton.jsxやInputField.jsxといったファイルを作成します。
ファイルを分けるときは、コンポーネントをexportキーワードで外部に公開し、使う側ではimportキーワードで読み込みます。これはJavaScriptのモジュールシステムという仕組みで、コードを整理するための標準的な方法です。
フォルダ構成を工夫することで、プロジェクトが大きくなっても管理しやすくなります。一般的には、共通コンポーネント用のフォルダ、ページ用のフォルダ、ユーティリティ関数用のフォルダなどに分けて整理します。こうすることで、チームで開発する際にも、どこに何があるか分かりやすくなります。
9. propsのデフォルト値を設定する方法
共通コンポーネントを作るときは、propsにデフォルト値を設定しておくと便利です。デフォルト値とは、値が指定されなかったときに使われる初期値のことです。これにより、最小限のpropsだけでコンポーネントを使えるようになります。
デフォルト値の設定方法はいくつかありますが、最も簡単なのは||演算子を使う方法です。例えば、props.color || "#007bff"と書くと、colorが指定されていない場合に青色が使われます。また、分割代入という機能を使って、デフォルト値を設定することもできます。
propsの型をチェックする仕組みもあります。PropTypesというライブラリを使うと、間違った型のデータが渡されたときに警告を表示できます。これにより、バグを早期に発見でき、より堅牢なアプリケーションを作ることができます。
10. 共通コンポーネント作成のベストプラクティス
共通コンポーネントを作るときは、いくつかの重要なポイントがあります。まず、コンポーネントは一つの責任だけを持つようにしましょう。ボタンはボタンの機能だけ、入力フォームは入力の機能だけを担当するようにします。複数の機能を一つのコンポーネントに詰め込むと、再利用しにくくなってしまいます。
また、コンポーネントの名前は分かりやすく付けることが大切です。Button、InputField、Cardなど、見ただけで何をするコンポーネントか分かる名前にしましょう。略語は避けて、完全な単語を使うことをおすすめします。
さらに、スタイルの指定方法にも注意が必要です。インラインスタイルは手軽ですが、プロジェクトが大きくなるとCSSファイルやスタイルドコンポーネントという方法を検討すると良いでしょう。共通コンポーネントのスタイルは統一感を持たせることで、アプリケーション全体のデザインが洗練されます。定期的にコンポーネントを見直し、改善することも忘れないようにしましょう。