React

Lesson 10

Composition over prop flags

Prefer flexible component slots over growing boolean prop combinations.

Good Code

Panel.tsx
import type { ReactNode } from "react";

type PanelProps = {
  title: string;
  tone?: "neutral" | "danger";
  actions?: ReactNode;
  children: ReactNode;
};

export function Panel({
  title,
  tone = "neutral",
  actions,
  children,
}: PanelProps) {
  // Slots let callers compose the variant-specific UI.
  return (
    <section data-tone={tone}>
      <header>
        <h2>{title}</h2>
        {actions}
      </header>
      <div>{children}</div>
    </section>
  );
}

export function DeleteReviewPanel({ onDelete }: { onDelete: () => void }) {
  return (
    <Panel
      title="Delete review"
      tone="danger"
      actions={<button type="button" onClick={onDelete}>Delete</button>}
    >
      <p>This review and its comments will be removed.</p>
    </Panel>
  );
}

Bad Code

Panel.tsx
import type { ReactNode } from "react";

type PanelProps = {
  title: string;
  mode: "details" | "delete" | "approval";
  showFooter: boolean;
  showDeleteButton: boolean;
  onDelete?: () => void;
  children: ReactNode;
};

export function Panel({
  title,
  mode,
  showFooter,
  showDeleteButton,
  onDelete,
  children,
}: PanelProps) {
  // Boolean flags create combinations the component must police.
  return (
    <section data-mode={mode}>
      <h2>{title}</h2>
      <div>{children}</div>
      {showFooter ? <footer>Review actions</footer> : null}
      {showDeleteButton ? (
        <button type="button" onClick={onDelete}>Delete</button>
      ) : null}
    </section>
  );
}

Review Notes

What to review

Good Code

The good version gives callers a clear slot for actions and content, so each variant composes the panel it needs.

Bad Code

The bad version grows mode and boolean props for every new variation. Those combinations make the component harder to understand and easier to call incorrectly.

Takeaways

  • Use children and named slots when a component has multiple content variants.