AI時代のReact入門 第7回:プロップスの使い方

「同じボタンなのに、文字だけ変えたい…」 「カードのデザインは同じだけど、タイトルと内容を変えたい…」

Reactのコンポーネントを作ってみたものの、このような悩みを持ったことはありませんか?実は、propsを使えば、同じコンポーネントを異なる内容で表示できるんです。

今回は、Reactの重要な概念「props」の使い方を、実践的なコード例を交えながら解説していきます。この記事を読めば、コンポーネントを自在にカスタマイズできるようになり、Reactの真の力を実感できるはずです。

Reactのprops:コンポーネントをカスタマイズする方法を学ぼう

「同じボタンなのに、文字だけ変えたい…」 「カードのデザインは同じだけど、タイトルと内容を変えたい…」

Reactのコンポーネントを作ってみたものの、このような悩みを持ったことはありませんか?実は、propsを使えば、同じコンポーネントを異なる内容で表示できるんです。

今回は、Reactの重要な概念「props」の使い方を、実践的なコード例を交えながら解説していきます。この記事を読めば、コンポーネントを自在にカスタマイズできるようになり、Reactの真の力を実感できるはずです。

propsとは何か

propsは「properties(プロパティ)」の略で、コンポーネントに渡すデータのことです。HTMLの属性に似ていますが、より柔軟にデータを扱えます。

たとえば、従来のHTMLでは以下のようにボタンを書いていました:

HTML
<button type="button" class="primary">送信する</button>
<button type="button" class="secondary">キャンセル</button>

Reactでpropsを使うと、このように書けます:

jsx
<Button text="送信する" variant="primary" />
<Button text="キャンセル" variant="secondary" />

propsの基本的な使い方

propsの受け取り方

jsx
function Button(props) {
  return (
    <button className={`button ${props.variant}`}>
      {props.text}
    </button>
  );
}

より一般的な書き方として、分割代入を使用します:

jsx
function Button({ text, variant }) {
  return (
    <button className={`button ${variant}`}>
      {text}
    </button>
  );
}

デフォルト値の設定

propsが渡されなかった場合のデフォルト値を設定できます:

jsx
function Button({ text = 'クリック', variant = 'primary' }) {
  return (
    <button className={`button ${variant}`}>
      {text}
    </button>
  );
}

実践的なpropsの活用例

汎用ボタンコンポーネント

jsx
const Button = ({ text = 'クリック', variant = 'primary', onClick, disabled = false }) => {
  const baseStyle = 'px-4 py-2 rounded font-medium focus:outline-none transition-colors';
  
  const variantStyles = {
    primary: 'bg-blue-500 text-white hover:bg-blue-600',
    secondary: 'bg-gray-500 text-white hover:bg-gray-600',
    outline: 'border-2 border-blue-500 text-blue-500 hover:bg-blue-50'
  };

  return (
    <button 
      className={`${baseStyle} ${variantStyles[variant]}`}
      onClick={onClick}
      disabled={disabled}
    >
      {text}
    </button>
  );
};

// 使用例を表示するためのデモコンポーネント
const ButtonDemo = () => {
  return (
    <div className="space-y-4">
      <div className="space-x-4">
        <Button text="送信する" />
        <Button text="キャンセル" variant="secondary" />
        <Button text="詳細を見る" variant="outline" />
      </div>
      <div className="space-x-4">
        <Button disabled text="送信する" />
        <Button disabled text="キャンセル" variant="secondary" />
      </div>
    </div>
  );
};

export default ButtonDemo;

カードコンポーネント

続いて、カードコンポーネントも作ってみましょう:

jsx
const Card = ({ title, description, image, variant = 'default' }) => {
  const baseStyle = 'rounded-lg overflow-hidden shadow-md';
  
  const variantStyles = {
    default: 'bg-white',
    highlighted: 'bg-blue-50 border-2 border-blue-200'
  };

  return (
    <div className={`${baseStyle} ${variantStyles[variant]}`}>
      {image && (
        <img 
          src={image} 
          alt={title} 
          className="w-full h-48 object-cover"
        />
      )}
      <div className="p-4">
        <h3 className="text-xl font-bold mb-2">{title}</h3>
        <p className="text-gray-600">{description}</p>
      </div>
    </div>
  );
};

// 使用例を表示するためのデモコンポーネント
const CardDemo = () => {
  return (
    <div className="grid grid-cols-2 gap-4">
      <Card 
        title="はじめてのReact"
        description="Reactの基礎を学びましょう。コンポーネントとpropsについて解説します。"
      />
      <Card 
        title="上級者向けReact"
        description="パフォーマンスチューニングとベストプラクティスについて解説します。"
        variant="highlighted"
      />
    </div>
  );
};

export default CardDemo;

よくある間違いと解決方法

1. propsの分割代入を忘れる

jsx
// ❌ 冗長な書き方
function Button(props) {
  return <button>{props.text}</button>;
}

// ✅ 分割代入を使用した書き方
function Button({ text }) {
  return <button>{text}</button>;
}

2. propsの直接変更

jsx
// ❌ propsを直接変更してはいけない
function Button({ text }) {
  text = text.toUpperCase();  // ❌ エラー
  return <button>{text}</button>;
}

// ✅ 新しい変数に代入して使用
function Button({ text }) {
  const upperText = text.toUpperCase();  // OK
  return <button>{upperText}</button>;
}

3. props.childrenの使い忘れ

jsx
// ❌ 柔軟性に欠ける実装
function Button({ text }) {
  return <button>{text}</button>;
}

// ✅ childrenを使用した柔軟な実装
function Button({ children }) {
  return <button>{children}</button>;
}

// 使用例
<Button>
  <span>送信</span>
  <img src="icon.png" alt="" />
</Button>

まとめ

propsを使うことで、コンポーネントを柔軟にカスタマイズできることがわかりました。重要なポイントを復習しましょう:

  • propsはコンポーネントに渡すデータ
  • 分割代入を使って簡潔に書ける
  • デフォルト値を設定できる
  • childrenで子要素を受け取れる
  • propsは直接変更しない

次回は、コンポーネントの状態を管理する「useState」について学んでいきます。これを使えば、ユーザーの操作に応じて動的に変化するUIを作れるようになります。お楽しみに!