agentsclimarketplace

React patterns

Skill halflength-ampleness75/claude-code-recipes/skills/react-patterns

Provide ready-to-use Claude Code commands, subagents, hooks, skills, and configs to simplify setup and speed up development.

Install
npx -y skills add halflength-ampleness75/claude-code-recipes --skill react-patterns

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

6.5 KB, as published. Nobody here has run it

React Patterns

Best practices for React development: functional components, hooks, state management, performance, and accessibility.

Component Rules

  1. Always use functional components — never class components for new code
  2. One component per file — name the file the same as the component (PascalCase)
  3. Export components as named exports — default exports only for pages/routes
  4. Colocate related files — keep Component.tsx, Component.test.tsx, and Component.module.css together
  5. Props interface above the component — name it ComponentNameProps
// Good
interface UserCardProps {
  user: User;
  onSelect: (id: string) => void;
  variant?: "compact" | "full";
}

export function UserCard({ user, onSelect, variant = "full" }: UserCardProps) {
  return ( /* ... */ );
}
// Bad — default export, inline props, class component
export default class UserCard extends React.Component<{user: any}> { /* ... */ }

Hooks Patterns

Custom Hooks

  1. Prefix with useuseAuth, useDebounce, useLocalStorage
  2. Extract shared logic into custom hooks — if two components share stateful logic, extract it
  3. Return tuples for simple hooks, objects for complex ones
// Simple: return tuple
function useToggle(initial = false): [boolean, () => void] {
  const [value, setValue] = useState(initial);
  const toggle = useCallback(() => setValue((v) => !v), []);
  return [value, toggle];
}

// Complex: return object
function useApi<T>(url: string) {
  const [data, setData] = useState<T | null>(null);
  const [error, setError] = useState<Error | null>(null);
  const [loading, setLoading] = useState(true);
  // ... fetch logic
  return { data, error, loading, refetch };
}

Hook Rules

  1. Never call hooks conditionally — all hooks must run on every render
  2. Use useCallback for functions passed to children — prevents unnecessary re-renders
  3. Use useMemo only for expensive computations — don't wrap everything
  4. Prefer useReducer over useState when state transitions are complex

useEffect Guidelines

  1. Always specify dependencies — never use // eslint-disable-next-line
  2. Return a cleanup function for subscriptions, timers, and listeners
  3. Avoid setting state in useEffect when you can derive it — computed values don't need effects
// Bad — unnecessary effect
const [fullName, setFullName] = useState("");
useEffect(() => {
  setFullName(`${firstName} ${lastName}`);
}, [firstName, lastName]);

// Good — derived value
const fullName = `${firstName} ${lastName}`;

State Management Tiers

Use the simplest tier that solves the problem:

TierToolWhen to Use
1. Local stateuseState, useReducerSingle component state
2. Lifted stateProps, compositionShared between parent/child
3. ContextcreateContext + useContextTheme, auth, locale — rarely changes
4. URL stateSearch params, path paramsFilters, pagination, navigation state
5. Server stateReact Query / SWRAPI data, caching, synchronization
6. Global storeZustand / Redux ToolkitComplex client state across many components

Context Guidelines

  1. Split contexts by domainAuthContext, ThemeContext, not AppContext
  2. Keep context values stable — use useMemo on the provider value
  3. Don't put frequently changing values in context — it re-renders all consumers
// Good — stable context value
function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<User | null>(null);

  const value = useMemo(() => ({ user, setUser }), [user]);

  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}

Performance

  1. Use React.lazy + Suspense for route-level code splitting
  2. Memoize expensive list items with React.memo — include a custom comparator if props are objects
  3. Virtualize long lists — use react-window or @tanstack/virtual for 100+ items
  4. Avoid anonymous functions in JSX when passing to memoized children
  5. Use key correctly — stable, unique identifiers, never array index for dynamic lists
// Good — code splitting
const Dashboard = lazy(() => import("./pages/Dashboard"));

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <Routes>
        <Route path="/dashboard" element={<Dashboard />} />
      </Routes>
    </Suspense>
  );
}

Accessibility

  1. Use semantic HTML<button> not <div onClick>, <nav> not <div className="nav">
  2. All images need alt text — empty alt="" for decorative images
  3. Form inputs need labels — use <label htmlFor> or aria-label
  4. Manage focus on route changes — focus the main heading after navigation
  5. Support keyboard navigation — all interactive elements must be reachable via Tab
  6. Use ARIA attributes when semantic HTML is insufficientaria-expanded, aria-live, role
// Good — accessible modal
function Modal({ isOpen, onClose, title, children }: ModalProps) {
  const closeRef = useRef<HTMLButtonElement>(null);

  useEffect(() => {
    if (isOpen) closeRef.current?.focus();
  }, [isOpen]);

  if (!isOpen) return null;

  return (
    <div role="dialog" aria-modal="true" aria-labelledby="modal-title">
      <h2 id="modal-title">{title}</h2>
      {children}
      <button ref={closeRef} onClick={onClose}>
        Close
      </button>
    </div>
  );
}

Error Boundaries

  1. Wrap route-level components in error boundaries
  2. Provide a meaningful fallback UI — not just "Something went wrong"
  3. Log errors to your monitoring service in the boundary
import { ErrorBoundary } from "react-error-boundary";

function ErrorFallback({ error, resetErrorBoundary }: FallbackProps) {
  return (
    <div role="alert">
      <h2>Something went wrong</h2>
      <pre>{error.message}</pre>
      <button onClick={resetErrorBoundary}>Try again</button>
    </div>
  );
}

// Usage
<ErrorBoundary FallbackComponent={ErrorFallback}>
  <Dashboard />
</ErrorBoundary>

Anti-patterns

  • Prop drilling more than 2 levels — use composition or context instead
  • Giant useEffect blocks — split into multiple focused effects
  • Storing derived state — compute it during render
  • Premature optimization — profile before adding useMemo/useCallback everywhere
  • String-based refs — use useRef only
  • Direct DOM manipulation — use refs only when React APIs are insufficient

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.