mcpField
R
react-design-patterns

react-design-patterns

github.com/b4r7xDevelopment046 installsUpdated 12w ago
Repository

About react-design-patterns

A reference skill for React developers choosing among 13 component and application design patterns. It includes a decision guide and favors starting with Custom Hooks before adopting more structural patterns.

Key features

  1. 01Decision guide for pattern selection
  2. 02Covers 13 React design patterns
  3. 03Explains controlled and uncontrolled components
  4. 04Shows logic and presentation separation
  5. 05Includes guidance on errors and portals

Use cases

  1. 01Choosing a pattern for reusable component logic
  2. 02Designing compound Tabs or Modal components
  3. 03Separating data fetching from rendering
  4. 04Structuring a design system

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/b4r7x/agent-skills --skill react-design-patterns

After installing, type/react-design-patternsin Claude Code to confirm it loaded.

Details

From the project README

React Design Patterns

Overview

13 patterns ranked by 2025 popularity. Golden rule: start with a Custom Hook — upgrade to Compound Components only if structural sharing is needed.

Pattern Decision Guide

NeedPattern
Reusable logic, no UI opinionCustom Hook
Controlled vs uncontrolled component behaviorControl Props
Tightly coupled UI subcomponents (Tabs, Modal, Accordion)Compound Components
Logic without imposed stylingHeadless Component
Separate data fetching from renderingContainer / Presentational
Global stable state (auth, theme)Provider (Context)
Reverse data flow (child → parent)Render Props
Full render control via childrenChildren as Function
Flexible API with pre-built propsProps Getters
Crash isolationError Boundary
Render outside DOM parent (modals, tooltips)Portal
Design system hierarchyAtomic Design

1. Custom Hook ⭐⭐⭐⭐⭐

Extract stateful logic into a reusable function. Most popular pattern in 2025.

function useLocalStorage(key, initialValue) {
  const [value, setValue] = useState(() => {
    try { return JSON.parse(localStorage.getItem(key)) ?? initialValue; }
    catch { return initialValue; }
  });
  const set = useCallback((v) => {
    setValue(prev => {
      const next = v instanceof Function ? v(prev) : v;
      localStorage.setItem(key, JSON.stringify(next));
      return next;
    });
  }, [key]);
  return [value, set];
}

2. Control Props ⭐⭐⭐⭐

Component supports both controlled (parent owns state via props) and uncontrolled (manages own state) modes. Every form input and component library uses this.

// Controlled — parent manages state
<EditableTitle title={title} onChange={setTitle} />

// Uncontrolled — component manages own state, parent can reset via key
<EditableTitle key={userId} defaultTitle="Untitled" />

// Implementation supporting both modes
function EditableTitle({ title, defaultTitle = '', onChange }) {
  const [internal, setInternal] = useState(defaultTitle);
  const isControlled = title !== undefined;
  const value = isControlled ? title : internal;

  const handleChange = (e) => {
    if (!isControlled) setInternal(e.target.value);
    onChange?.(e.target.value);
  };

  return <input value={value} onChange={handleChange} />;
}

3. Compound Components ⭐⭐⭐⭐

Family of subcomponents sharing state via local context. Used by Radix UI, Headless UI, React Aria.

const TabsContext = createContext(null);
function Tabs({ children, defaultTab }) { /* owns [activeTab, setActiveTab], provides both via context */ }
Tabs.Tab = /* reads context, renders the trigger button */
Tabs.Panel = /* reads context, renders children when active */

Shape: the parent owns the state and provides it via local context; dot-namespaced subcomponents consume it; a useTabs() guard hook throws when a subcomponent renders outside <Tabs>. The full runnable implementation lives in the react-usecontext skill (single owner of this example) — load it when you build one.

4. Headless Component ⭐⭐⭐⭐

Hook provides logic only — zero HTML, zero CSS. You own the UI completely.

function useAccordion() {
  const [openIndex, setOpenIndex] = useState(null);
  const toggle = useCallback((i) => setOpenIndex(prev => prev === i ? null : i), []);
  const isOpen = useCallback((i) => openIndex === i, [openIndex]);
  return { toggle, isOpen };
}
// Two completely different UIs can use the same hook

5. Container / Presentational ⭐⭐⭐

Split into: Container (logic, fetch, navigation) and Presentational (receives data via props, renders only).

// Presentational — pure UI, easy to test
const UserCard = ({ user, onFollow }) => (
  <div><h2>{user.name}</h2><button onClick={onFollow}>Follow</button></div>
);
// Container — logic and data
const UserCardContainer = ({ userId }) => {
  const { user, follow } = useUser(userId);
  if (!user) return <Skeleton />;
  return <UserCard user={user} onFollow={follow} />;
};

6. Provider (Context) ⭐⭐⭐⭐

createContext + useContext for global/local state. See react-usecontext skill for full details.

7. Render Props ⭐⭐

Pass a function as prop — component calls it with data:

<WindowSize render={({ width }) => (
  width < 768 ? <MobileMenu /> : <DesktopMenu />
)} />

Useful for reverse data flow (child → parent). Mostly replaced by custom hooks in 2025.

8. Children as Function ⭐⭐

Variant of render props — function passed as children. Popularized by Formik, Downshift:

<Toggle>
  {({ on, toggle }) => (
    <button onClick={toggle}>{on ? 'ON' : 'OFF'}</button>
  )}
</Toggle>

9. Props Getters ⭐⭐

Hook returns pre-built prop objects to spread on elements. Used by React Hook Form (register), react-table:

function useToggle() {
  const [on, setOn] = useState(false);
  const getTogglerProps = (overrides = {}) => ({
    onClick: () => setOn(prev => !prev),
    'aria-pressed': on,
    ...overrides,
  });
  return { on, getTogglerProps };
}
// Usage: <button {...getTogglerProps({ className: 'my-btn' })}>

10. Error Boundary ⭐⭐

Catches JS errors in the component tree, shows fallback UI. Requires class component or react-error-boundary library:

import { ErrorBoundary } from 'react-error-boundary';
<ErrorBoundary FallbackComponent={ErrorFallback} onReset={() => { /* reset state */ }}>
  <Dashboard />
</ErrorBoundary>

Underused — most apps should have granular error boundaries per section.

11. Portal ⭐⭐⭐

Renders outside the DOM parent tree. Solves z-index, overflow: hidden, clipping:

import { createPortal } from 'react-dom';
function Modal({ isOpen, children }) {
  if (!isOpen) return null;
  return createPortal(
    <div className="modal-overlay">{children}</div>,
    document.body
  );
}

12. HOC (Higher-Order Component) ⭐ — Legacy

Function that takes a component, returns a new component. Replaced by custom hooks in modern code.

// Legacy
const ProtectedDashboard = withAuth(Dashboard);
// Modern equivalent
function ProtectedRoute({ children }) {
  const { user } = useAuth();
  if (!user) return <Navigate to="/login" />;
  return children;
}

13. Atomic Design ⭐⭐⭐

Hierarchy: Atoms (Button) → Molecules (SearchBox = Input + Button) → Organisms (Header) → Templates (layout without data) → Pages (template with data). Great for design systems and large team projects.

References

Comments

Markdown supported