4.1 propsの型

type ButtonProps = {
  children: React.ReactNode;
  variant?: "primary" | "secondary";
  onClick?: () => void;
  disabled?: boolean;
};

function Button({
  children,
  variant = "primary",
  onClick,
  disabled = false,
}: ButtonProps) {
  return (
    <button
      type="button"
      data-variant={variant}
      onClick={onClick}
      disabled={disabled}
    >
      {children}
    </button>
  );
}

4.2 propsの設計原則

  • booleanの意味を明確にする
  • 相反するpropsを増やさない
  • ドメインの語彙を使う
  • 内部実装を露出しすぎない
  • 未使用propsの透過は慎重に行う

悪い例:

<Modal
  small
  large
  noHeader
  showFooter
  type={3}
/>

改善例:

<Modal
  size="large"
  header={null}
  footer={<SaveActions />}
/>

4.3 コンポーネント合成

function Dialog({
  title,
  body,
  actions,
}: {
  title: React.ReactNode;
  body: React.ReactNode;
  actions: React.ReactNode;
}) {
  return (
    <section role="dialog" aria-modal="true">
      <header>{title}</header>
      <div>{body}</div>
      <footer>{actions}</footer>
    </section>
  );
}

スロットをpropsとして渡すと、特定画面への依存を避けられる。

4.4 コンポーネントを内側で定義しない

function Parent() {
  function Child() {
    return <p>子</p>;
  }

  return <Child />;
}

この書き方では、Parentのレンダリングごとに別のコンポーネント型が作られ、stateがリセットされる原因になる。通常はモジュールのトップレベルへ出す。