Skill
Community

react-patterns

Install
1
Install the plugin
$
npx claudepluginhub peopleforrester/claude-dotfiles

Want just this skill?

Then install: npx claudepluginhub u/[userId]/[slug]

Description

React 19+ best practices and patterns. Covers hooks, composition, server components, performance optimization, and state management. Use when building React components or reviewing React code.

Tool Access

This skill uses the workspace's default tool permissions.

Skill Content

React Patterns

Modern React 19+ patterns and best practices.

Component Patterns

Composition Over Prop Drilling

// Compose with children instead of passing many props
<Card>
  <Card.Header>
    <Card.Title>User Profile</Card.Title>
  </Card.Header>
  <Card.Body>
    <UserInfo user={user} />
  </Card.Body>
  <Card.Footer>
    <Button onClick={save}>Save</Button>
  </Card.Footer>
</Card>

Render Props for Flexibility

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

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

Hook Patterns

Custom Data Fetching Hook

function useQuery<T>(key: string, fetcher: () => Promise<T>) {
  const [state, setState] = useState<{
    data: T | null;
    error: Error | null;
    isLoading: boolean;
  }>({ data: null, error: null, isLoading: true });

  useEffect(() => {
    let cancelled = false;
    setState(prev => ({ ...prev, isLoading: true }));

    fetcher()
      .then(data => { if (!cancelled) setState({ data, error: null, isLoading: false }); })
      .catch(error => { if (!cancelled) setState({ data: null, error, isLoading: false }); });

    return () => { cancelled = true; };
  }, [key]);

  return state;
}

useCallback for Stable References

const handleSubmit = useCallback(
  async (data: FormData) => {
    await api.submit(userId, data);
    onSuccess();
  },
  [userId, onSuccess]
);

useMemo for Expensive Computations

const sortedItems = useMemo(
  () => [...items].sort((a, b) => a.name.localeCompare(b.name)),
  [items]
);

State Management

Local State First

// Start simple
const [isOpen, setIsOpen] = useState(false);

// Graduate to useReducer for complex state
const [state, dispatch] = useReducer(cartReducer, initialCart);

// Context for cross-component state
const ThemeContext = createContext<Theme>('light');

Server State (React Query / SWR)

const { data, isLoading } = useQuery({
  queryKey: ['users', userId],
  queryFn: () => fetchUser(userId),
  staleTime: 5 * 60 * 1000,
});

Performance

Code Splitting

const Dashboard = lazy(() => import('./Dashboard'));

function App() {
  return (
    <Suspense fallback={<Skeleton />}>
      <Dashboard />
    </Suspense>
  );
}

Virtualization for Long Lists

import { useVirtualizer } from '@tanstack/react-virtual';

function VirtualList({ items }: { items: Item[] }) {
  const parentRef = useRef<HTMLDivElement>(null);
  const virtualizer = useVirtualizer({
    count: items.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 50,
  });

  return (
    <div ref={parentRef} style={{ overflow: 'auto', height: 400 }}>
      {virtualizer.getVirtualItems().map(row => (
        <div key={row.key} style={{ transform: `translateY(${row.start}px)` }}>
          {items[row.index].name}
        </div>
      ))}
    </div>
  );
}

Error Boundaries

class ErrorBoundary extends Component<Props, { hasError: boolean }> {
  state = { hasError: false };

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  render() {
    if (this.state.hasError) return this.props.fallback;
    return this.props.children;
  }
}

Checklist

  • Functional components only (no class components for new code)
  • Custom hooks for reusable stateful logic
  • Correct dependency arrays in useEffect/useCallback/useMemo
  • Error boundaries at route level
  • Loading and error states handled for async data
  • Accessibility: ARIA labels, keyboard navigation, focus management
  • Code splitting for route-level components
  • Keys use stable, unique identifiers (not array index)
Stats
Stars0
Forks0
Last CommitFeb 5, 2026

Similar Skills