Skip to content
Back to skills

React Advanced Patterns

ASecurity

Implements advanced React patterns including render props, higher-order components, custom hooks composition, portals, error boundaries, and ref forwarding for complex component architectures.

  • 4 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added June 12, 2026
developmenttypescriptgoreactnodedebugginggitapidocumentation

Works with

  • cli
  • api

Security analysis

A100/100

Scanned June 12, 2026

npx -y skills add paulpas/agent-skill-router --skill react-advanced-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of React Advanced Patterns?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for React Advanced Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/paulpas-react-advanced-patterns/badge)](https://www.skillsdirectory.com/skills/paulpas-react-advanced-patterns)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: react-advanced-patterns
description: Implements advanced React patterns including render props, higher-order components, custom hooks composition, portals, error boundaries, and ref forwarding for complex component architectures.
license: MIT
compatibility: opencode
archetypes:
  - tactical
  - generation
anti_triggers:
  - brainstorming
  - vague ideation
  - long-form architecture
response_profile:
  verbosity: low
  directive_strength: high
  abstraction_level: operational
metadata:
  version: "1.0.0"
  domain: coding
  triggers: react advanced, custom hooks, error boundary, react portal, hoc, forward ref, render props
  role: implementation
  scope: implementation
  output-format: code
  content-types: [code, guidance, do-dont, examples]
  related-skills: react-composition-patterns, react-rerender-optimization, react-client-data-fetching
  author: https://github.com/vercel-labs
  source: https://github.com/vercel-labs/agent-skills
---

# Advanced React Patterns

Implements advanced React patterns for cross-cutting concerns: custom hooks for stateful logic reuse, higher-order components for configuration injection, render props for flexible rendering, portals for out-of-DOM rendering, error boundaries for graceful failure, and ref forwarding for imperative access.

## TL;DR Checklist

- [ ] Choose hooks over HOCs for stateful logic reuse
- [ ] Compose small hooks into larger ones following the single-responsibility principle
- [ ] Use createPortal for modals, tooltips, and dropdowns outside parent DOM hierarchy
- [ ] Implement error boundaries at route and feature boundaries
- [ ] Set displayName on all HOCs for debugging
- [ ] Use forwardRef when wrapping native DOM elements
- [ ] Test each pattern in isolation before composing

---

## When to Use

Use this skill when:

- Extracting reusable stateful logic shared across multiple components
- Building modals, tooltips, or dropdowns that need to escape overflow/scroll containers
- Adding error catch-all boundaries to feature sections or routes
- Wrapping third-party DOM elements that need ref access through component layers
- Implementing cross-cutting concerns (logging, analytics, authentication) across many components
- Creating flexible component APIs where the consumer controls rendering
- Exposing imperative methods (scrollTo, focus, reset) on a component via refs

---

## When NOT to Use

Avoid this skill for:

- Simple state management — useState and useEffect suffice
- One-off UI patterns that don't need reuse — premature abstraction
- Async data fetching without shared logic — use `react-client-data-fetching` instead
- Components that never expose refs or need portal rendering
- Situations where custom hooks already solve the problem — don't add HOC complexity

---

## Core Workflow

1. **Identify the Cross-Cutting Concern** — Is it state logic, configuration injection, flexible rendering, or DOM escape? Each maps to a different pattern.

2. **Select the Appropriate Pattern**:
   - Stateful logic → custom hooks
   - Configuration/behavior injection → HOC
   - Flexible render control → render props
   - Escape parent container → portals (createPortal)
   - Catch rendering errors → error boundaries
   - Expose imperative methods → forwardRef + useImperativeHandle

3. **Implement with TypeScript** — Use proper generic types for maximum reusability.

4. **Test in Isolation** — Verify each pattern works independently before composing multiple patterns together.

---

## Implementation Patterns

### Pattern 1: Custom Hooks Composition

```typescript
// ✅ GOOD: Small, composable hooks — each has one responsibility
function useLocalStorage<T>(key: string, initialValue: T) {
  const [storedValue, setStoredValue] = useState<T>(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? (JSON.parse(item) as T) : initialValue;
    } catch {
      return initialValue;
    }
  });

  const setValue = useCallback(
    (value: T | ((prev: T) => T)) => {
      setStoredValue((prev) => {
        const valueToStore = value instanceof Function ? value(prev) : value;
        window.localStorage.setItem(key, JSON.stringify(valueToStore));
        return valueToStore;
      });
    },
    [key]
  );

  return [storedValue, setValue] as const;
}

function useMediaQuery(query: string): boolean {
  const [matches, setMatches] = useState(() => matchMedia(query).matches);

  useEffect(() => {
    const mql = matchMedia(query);
    const handler = (e: MediaQueryListEvent) => setMatches(e.matches);
    mql.addEventListener('change', handler);
    return () => mql.removeEventListener('change', handler);
  }, [query]);

  return matches;
}

// Compose them for a complex behavior
function useResponsiveLocalStorage<T>(key: string, initialValue: T) {
  const [value, setValue] = useLocalStorage(key, initialValue);
  const isMobile = useMediaQuery('(max-width: 768px)');

  const adjustedValue = useMemo(
    () => (isMobile ? truncateForMobile(value) : value),
    [value, isMobile]
  );

  return [adjustedValue, setValue] as const;
}
```

### Pattern 2: Error Boundary with Granular Fallback (BAD vs. GOOD)

```typescript
// ❌ BAD: Class component error boundary — works but verbose and lacks TypeScript generics
class ErrorBoundary extends React.Component {
  state = { hasError: false, error: null };
  static getDerivedStateFromError(error: Error) {
    return { hasError: true, error };
  }
  render() {
    if (this.state.hasError) return <h1>Something went wrong</h1>;
    return this.props.children;
  }
}
```

```typescript
// ✅ GOOD: Error boundary with typed fallback component and granular control
interface ErrorBoundaryProps {
  children: React.ReactNode;
  fallback?: React.ComponentType<{ error: Error; reset: () => void }>;
  onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
}

interface ErrorBoundaryState {
  hasError: boolean;
  error: Error | null;
}

class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
  constructor(props: ErrorBoundaryProps) {
    super(props);
    this.state = { hasError: false, error: null };
  }

  static getDerivedStateFromError(error: Error): ErrorBoundaryState {
    return { hasError: true, error };
  }

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
    this.props.onError?.(error, errorInfo);
  }

  handleReset = () => {
    this.setState({ hasError: false, error: null });
  };

  render(): React.ReactNode {
    if (this.state.hasError && this.state.error) {
      const Fallback = this.props.fallback;
      if (Fallback) {
        return <Fallback error={this.state.error} reset={this.handleReset} />;
      }
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}

// Usage: wrap routes or feature sections
<ErrorBoundary
  fallback={({ error, reset }) => (
    <div role="alert">
      <h2>Section failed to load</h2>
      <pre>{error.message}</pre>
      <button onClick={reset}>Retry</button>
    </div>
  )}
  onError={(err) => logErrorToService(err)}
>
  <UserProfile userId={id} />
</ErrorBoundary>
```

### Pattern 3: Portal for Modal Rendering

```typescript
// ✅ GOOD: Portal-based modal escapes parent overflow/stacking context
import { createPortal } from 'react-dom';

interface PortalProps {
  children: React.ReactNode;
  container?: Element | DocumentFragment;
}

function Portal({ children, container = document.body }: PortalProps) {
  return createPortal(children, container);
}

function Modal({ isOpen, onClose, children }: ModalProps) {
  useEffect(() => {
    const handleEscape = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose();
    };

    if (isOpen) {
      document.addEventListener('keydown', handleEscape);
      document.body.style.overflow = 'hidden';
    }

    return () => {
      document.removeEventListener('keydown', handleEscape);
      document.body.style.overflow = '';
    };
  }, [isOpen, onClose]);

  if (!isOpen) return null;

  return createPortal(
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal-content" onClick={(e) => e.stopPropagation()}>
        {children}
      </div>
    </div>,
    document.body
  );
}
```

### Pattern 4: forwardRef + useImperativeHandle

```typescript
// ✅ GOOD: Expose imperative methods through forwarded ref
interface FancyInputHandle {
  focus: () => void;
  reset: () => void;
  select: () => void;
}

interface FancyInputProps {
  defaultValue?: string;
  onValueChange?: (value: string) => void;
}

const FancyInput = forwardRef<FancyInputHandle, FancyInputProps>(
  function FancyInput({ defaultValue, onValueChange }, ref) {
    const inputRef = useRef<HTMLInputElement>(null);

    useImperativeHandle(
      ref,
      () => ({
        focus: () => inputRef.current?.focus(),
        reset: () => {
          if (inputRef.current) {
            inputRef.current.value = defaultValue ?? '';
            onValueChange?.(defaultValue ?? '');
          }
        },
        select: () => inputRef.current?.select(),
      }),
      [defaultValue, onValueChange]
    );

    return (
      <input
        ref={inputRef}
        defaultValue={defaultValue}
        onChange={(e) => onValueChange?.(e.target.value)}
      />
    );
  }
);

// Parent uses imperative handle
function Form() {
  const inputRef = useRef<FancyInputHandle>(null);

  return (
    <>
      <FancyInput ref={inputRef} defaultValue="hello" />
      <button onClick={() => inputRef.current?.reset()}>Reset</button>
    </>
  );
}
```

---

## Constraints

### MUST DO
- Use custom hooks over HOCs for stateful logic reuse
- Set `displayName` on every HOC for debugging (DevTools)
- Use `createPortal` for modals, dialogs, tooltips, and dropdowns
- Implement error boundaries at route, feature, or widget boundaries
- Use `forwardRef` when wrapping native DOM elements
- Expose imperative methods via `useImperativeHandle` when a component needs focus/reset/scroll
- Clean up portal DOM nodes and event listeners on unmount

### MUST NOT DO
- Over-abstract simple patterns — choose the simplest pattern that works
- Use render props or HOCs when custom hooks suffice
- Forget to reset error boundary state before retrying
- Nest portals unnecessarily — one level of portal is usually sufficient
- Ignore the ref type parameter on forwardRef — always type the handle interface
- Forget displayName on HOCs — debugging becomes impossible in React DevTools

---

## Related Skills

| Skill | Purpose |
|---|---|
| `react-composition-patterns` | Component composition patterns for building flexible UIs |
| `react-rerender-optimization` | Memoization strategies to avoid unnecessary re-renders |
| `react-client-data-fetching` | Data fetching patterns with Suspense and error boundaries |
| `react-async-waterfalls` | Avoiding request waterfalls in component hierarchies |

---

## Live References

> Authoritative documentation links for this skill's domain. The model follows markdown links at load time to resolve external references and inline content.

- [React.createPortal API](https://react.dev/reference/react-dom/createPortal)
- [React Error Boundaries](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary)
- [React forwardRef API](https://react.dev/reference/react/forwardRef)
- [React useImperativeHandle](https://react.dev/reference/react/useImperativeHandle)
- [Reusing Logic with Custom Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks)
- [Higher-Order Components (Legacy)](https://react.dev/legacy/higher-order-components)
- [Render Props Pattern (Legacy)](https://react.dev/legacy/render-props)

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.