Skip to content

Instantly share code, notes, and snippets.

@viniazvd
Created March 3, 2026 18:24
Show Gist options
  • Select an option

  • Save viniazvd/da0a3c4e733a7e31a74a3fe1668e3312 to your computer and use it in GitHub Desktop.

Select an option

Save viniazvd/da0a3c4e733a7e31a74a3fe1668e3312 to your computer and use it in GitHub Desktop.
description globs alwaysApply
React-specific standards – async, bundle, memo, state, rendering, Suspense, Error Boundaries
**/*.tsx, **/*.jsx
false

React Standards

Apply only when working with React (TSX/JSX). General JS/TS rules are in js-ts-react-standards.mdc.


7. React

7.1 Async & Data

  • Promise.all() for independent ops (no waterfalls)
  • Prefer Suspense for data loading when possible; defer await to where needed; streaming where supported
  • SWR or similar for client-side data fetching/cache

7.2 Bundle

  • Direct imports; avoid barrel files when possible
  • React.lazy + Suspense for heavy components (code-split)
  • Analytics/logging after hydration
  • Preload on hover/focus

7.3 Memo & derived values

  • Prefer simple computed constants in render over useMemo when the work is cheap (e.g. const fullName = user.firstName + ' ' + user.lastName)
  • Use useMemo only when: the computation is expensive, or you need referential stability (e.g. object in a dependency array, or child is memoized and receives the value)
  • Use useCallback only when: the function is passed to a memoized child or used in a dependency array that would otherwise change every render
  • Avoid wrapping every value/callback in useMemo/useCallback; measure before optimizing
// ✅ cheap derived value – no useMemo
const sortedItems = [...items].sort(byDate);
const isEmpty = items.length === 0;

// ✅ useMemo when expensive or referentially sensitive
const chartData = useMemo(() => computeChartData(rawData), [rawData]);

7.4 Re-renders & State

  • Function in useState for expensive init: useState(() => compute())
  • Functional setState for stable callbacks
  • useTransition for loading/non-urgent updates
  • Derive state in render, not effects
  • Don't subscribe to state only used in callbacks

7.5 Rendering

  • Ternary for conditionals, not && (avoids 0/falsy bugs)
  • Hoist static JSX outside components
  • content-visibility for long lists
  • useTransition over loading spinners

7.6 JS Performance

  • Set/Map for O(1) lookups; toSorted() for immutability
  • Hoist RegExp outside loops; cache props in loops
  • Return early; combine filter+map into one pass
  • Passive listeners for scroll events

7.7 Resilience & UX (Suspense, Error Boundaries)

  • Error Boundary (what it is): A React component (class or wrapper lib) that catches errors that happen during render or lifecycle of its children. Instead of the whole app going blank, only that part of the tree shows a fallback UI (e.g. “Something went wrong”). The rest of the app keeps working.

  • Error Boundaries (when to use): Wrap each “section” of the app (e.g. sidebar, main content, a feature) so one failure doesn’t crash everything. Use them for errors in render/effects. For errors inside event handlers or async code, use normal try/catch—Error Boundaries don’t catch those.

  • Suspense: Use it to declare “this part is loading” at a boundary (e.g. around a route or a block of components). React can show a fallback (spinner/skeleton) there and stream the content when ready. Prefer this over spreading isLoading booleans in many components; one boundary often replaces several loading flags.

  • Loading and error in data flows: Every place that fetches data should handle both “loading” and “error.” Either use Suspense + Error Boundary (declarative) or explicit state (e.g. loading, error) and render accordingly. Never leave the user with a blank screen or no feedback.

  • List keys: React uses the key prop to know which item is which when the list changes. Use a stable, unique id from the data (e.g. item.id). Avoid using the array index as key when the list can be reordered, filtered, or items can be added/removed—otherwise React can reuse the wrong component and cause bugs or lost state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment