Get the FREE Ultimate OpenClaw Setup Guide →

react-component-architecture

Scanned
npx machina-cli add skill autohandai/community-skills/react-component-architecture --openclaw
Files (1)
SKILL.md
3.0 KB

React Component Architecture

Component Design Principles

  1. Single Responsibility - Each component does one thing well
  2. Composition Over Configuration - Use children and render props over prop drilling
  3. Colocation - Keep related code together (styles, tests, types)
  4. Controlled vs Uncontrolled - Be explicit about state ownership

Component Patterns

Compound Components

For complex UI with shared state:

const Tabs = ({ children, defaultValue }: TabsProps) => {
  const [active, setActive] = useState(defaultValue);
  return (
    <TabsContext.Provider value={{ active, setActive }}>
      {children}
    </TabsContext.Provider>
  );
};

Tabs.List = TabsList;
Tabs.Trigger = TabsTrigger;
Tabs.Content = TabsContent;

Render Props for Flexibility

When consumers need control over rendering:

interface ListProps<T> {
  items: T[];
  renderItem: (item: T, index: number) => ReactNode;
  keyExtractor: (item: T) => string;
}

function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
  return items.map((item, i) => (
    <Fragment key={keyExtractor(item)}>{renderItem(item, i)}</Fragment>
  ));
}

Custom Hooks for Logic Extraction

Extract reusable stateful logic:

function useToggle(initial = false) {
  const [state, setState] = useState(initial);
  const toggle = useCallback(() => setState(s => !s), []);
  const setTrue = useCallback(() => setState(true), []);
  const setFalse = useCallback(() => setState(false), []);
  return { state, toggle, setTrue, setFalse } as const;
}

Polymorphic Components

Components that render as different elements:

type PolymorphicProps<E extends ElementType> = {
  as?: E;
} & ComponentPropsWithoutRef<E>;

function Box<E extends ElementType = 'div'>({
  as,
  ...props
}: PolymorphicProps<E>) {
  const Component = as || 'div';
  return <Component {...props} />;
}

Props Patterns

Discriminated Union Props

For mutually exclusive prop combinations:

type ButtonProps =
  | { variant: 'link'; href: string; onClick?: never }
  | { variant: 'button'; onClick: () => void; href?: never };

Default Props with Destructuring

function Button({
  variant = 'primary',
  size = 'md',
  ...props
}: ButtonProps) {
  // ...
}

Performance Patterns

  1. Memoize expensive computations with useMemo
  2. Memoize callbacks passed to children with useCallback
  3. Split contexts by update frequency
  4. Use React.memo for pure presentational components
  5. Virtualize long lists with react-virtual or similar

File Structure

components/
  Button/
    Button.tsx        # Component
    Button.test.tsx   # Tests
    Button.types.ts   # Types (if complex)
    index.ts          # Re-export

Source

git clone https://github.com/autohandai/community-skills/blob/main/react-component-architecture/SKILL.mdView on GitHub

Overview

Adopt scalable React UI design using patterns like compound components, render props, hooks, and polymorphic components, all in TypeScript. It emphasizes single responsibility, composition over configuration, and colocating related code (styles, tests, and types) for maintainable components.

How This Skill Works

Technically, compounds use context to share state across subcomponents, and render props and custom hooks extract reusable logic. Polymorphic components support rendering as different elements via an as prop; discriminated unions enforce safe, mutually exclusive props; and each component's types, tests, and styles are colocated in its folder. Performance improvements come from memoization and splitting contexts where needed.

When to Use It

  • You need shared state across parts of a complex UI (e.g., Tabs) and want clean boundaries via compound components.
  • When consumers require control over rendering and layout (use render props or function as children).
  • You're building reusable, polymorphic UI elements that can render as multiple HTML tags with a single API.
  • You want strong type safety for prop combinations using discriminated unions.
  • You aim to optimize performance in large UIs by memoizing expensive work and splitting contexts.

Quick Start

  1. Step 1: Plan components and state boundaries with SRP; decide on shared state via context if needed.
  2. Step 2: Implement compound components, render props, and a custom hook to extract logic; add polymorphic as prop where appropriate.
  3. Step 3: Add TS types, tests, and organize files (types, tests, styles) in a dedicated component folder; apply memoization and context splitting as needed.

Best Practices

  • Start with Single Responsibility for every component.
  • Prefer composition over prop drilling using children or render props.
  • Colocate related code: keep styles, tests, and types alongside the component.
  • Use discriminated unions for clear, type-safe prop shapes.
  • Memoize expensive computations and callbacks; split contexts to minimize updates.

Example Use Cases

  • Tabs implemented with compound components sharing state via context.
  • Generic List component using renderItem for flexible rendering.
  • Polymorphic Box component with an as prop for different element types.
  • Button component using discriminated unions to switch between link and button behavior.
  • useToggle custom hook to extract reusable toggle logic.

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers