Reactでコンポーネントを設計している際、値が空のときはPropsのキー自体を渡したくない(undefinedを渡したくない)場面がありました。 例えば、HTML属性に余計な属性を付与したくない場合や、子コンポーネント側でdefaultPropsを適用させたい場合です。

論理演算子とスプレッド構文を組み合わせることで、簡潔に条件付き展開が可能です。

基本構文

{...(条件 && { キー名:  })}

実践的なコード例

関数コンポーネント

user_idが存在する場合のみ、子コンポーネントへ渡します。

const Parent = () => {
  const user_id = "12345";

  return (
    <Child 
      {...(user_id && { user_id })} 
    />
  );
};

子コンポーネントでの受け取り方

const Child = ({ user_id = "default_id" }) => {
  return <div>{user_id}</div>;
};

undefinedを渡した場合との挙動の違い

以下のコードで挙動の違いを確認できます。

<Child user_id={undefined} /> //①
<Child {...(false && { user_id: "12345" })} /> //②

①の場合、子コンポーネントにはuser_idというキーが存在しますが値はundefinedです。 ReactのdefaultPropsはキーが存在しない場合にのみ適用されるため、①ではデフォルト値が適用されません。

②の場合、条件が偽のときはスプレッド展開が行われないため、子コンポーネントにはuser_idというキー自体が存在しません。 そのためデフォルト値が正しく適用されます。

const Child = ({ user_id = "default_id" }) => {
  return <div>{user_id}</div>;
};
// ①の結果: undefined(デフォルト値が適用されない)
// ②の結果: "default_id"(デフォルト値が適用される)

複数のPropsをまとめて条件付き展開する

条件が同じ複数のPropsをまとめて展開することもできます。

const Parent = () => {
  const isAdmin = true;

  return (
    <Child
      {...(isAdmin && {
        role: "admin",
        canEdit: true,
        canDelete: true,
      })}
    />
  );
};

個別に書く場合と比べてコードがスッキリします。

<Child
  role={isAdmin ? "admin" : undefined}
  canEdit={isAdmin ? true : undefined}
  canDelete={isAdmin ? true : undefined}
/>

TypeScriptでの書き方

TypeScriptを使う場合、受け取るコンポーネント側でPropsの型定義をオプショナルにしておく必要があります。

type ChildProps = {
  user_id?: string;
  role?: string;
  canEdit?: boolean;
};

const Child = ({ user_id = "default_id", role, canEdit }: ChildProps) => {
  return (
    <div>
      <p>{user_id}</p>
      <p>{role}</p>
      <p>{canEdit ? "編集可能" : "編集不可"}</p>
    </div>
  );
};

クラスコンポーネントでの記述

class Parent extends React.Component {
  render() {
    const { user_id } = this.props;

    return (
      <Child
        {...(user_id && { user_id })}
      />
    );
  }
}

よくあるユースケース

disabled属性を条件付きで付与する

ボタンの活性・非活性をPropsで制御する場合

const Button = ({ isLoading, onClick, children }) => {
  return (
    <button
      onClick={onClick}
      {...(isLoading && { disabled: true })}
    >
      {children}
    </button>
  );
};

aria属性を条件付きで付与する

アクセシビリティ対応でaria属性を動的に付与する場合

const Modal = ({ isOpen, children }) => {
  return (
    <div
      {...(isOpen && { "aria-modal": true, role: "dialog" })}
    >
      {children}
    </div>
  );
};

この記事のまとめ

{...(条件 && { キー名: 値 })}の構文を使うことで、条件が偽のときはPropsのキー自体を渡さないようにできます。

  • undefinedを渡すのとは異なり、デフォルト値が正しく機能する
  • 複数のPropsをまとめて条件付き展開できる
  • disabledaria属性など、HTML属性の動的付与にも活用できる
  • TypeScriptではPropsの型定義を?でオプショナルにする

UIコンポーネントをラップする際にコードをスッキリ保つのに役立つテクニックです。



関連記事