1. Cheat sheets
  2. Developer Foundations

8 minReference

Frontend React and React Native cheat sheet

React for the web and React Native on a few screens: which hook to reach for, the effect traps that cause most bugs, server data, forms, an accessibility checklist, performance fixes, Testing Library queries and the mobile specifics. Keep it open while you build or review a screen.

The mental model in five lines

A component is a function from props and state to UI. Props come from the parent and are read-only; state belongs to the component and changes only through its setter. Every state change re-renders that component and its children. Effects are for syncing with things outside React (the network, timers, subscriptions), not for computing values. Data flows down, events flow up through callbacks (Components, State and effects).

Which hook? "I want to..."

Hooks run in the same order on every render. Call them at the top level of a component or a custom hook, never inside conditions, loops or after an early return.

I want to...Reach forWatch out forLesson
Remember a value that changes the UIuseStateUse the updater form setQty(q => q + 1) when the new value depends on the old oneState and effects
Handle state with many related transitionsuseReducerKeep the reducer pure; no fetches inside itState and effects
Show a value computed from props or stateA plain variable during renderDo not copy it into state and sync it with an effectState and effects
Skip an expensive calculation on re-renderuseMemoOnly after measuring; the React Compiler can do this for you where enabledAccessible and fast
Keep a callback identity stable for a memoized childuseCallbackUseless unless the child is wrapped in memo or uses it as a dependencyAccessible and fast
Hold a value that does not re-render (timer id, DOM node)useRefDo not read or write ref.current during renderState and effects
Sync with something outside ReactuseEffect with a cleanupList every value it reads in the dependency arrayState and effects
Measure layout before the browser paintsuseLayoutEffectBlocks paint; rareAccessible and fast
Share a value deep in the tree (theme, user, store id)createContext and useContextEvery consumer re-renders when the value changes; split contexts or memoize the valueComponents
Keep typing smooth while a big list filtersuseDeferredValue or useTransitionMarks work as non-urgent; does not make it fasterAccessible and fast
Make ids for label and input pairsuseIdNot for list keysForms
Reuse stateful logic in two componentsA custom hook named useSomethingEach caller gets its own state; hooks share logic, not dataComponents
Read a form action's pending state and resultuseActionState, useFormStatus (React 19)React 19 only; older code uses useState flagsForms
Show the result before the server confirmsuseOptimistic (React 19)Roll back and tell the user when the request failsServer data

Effect traps: if you see X, it is probably Y

Most React bugs on Mangrove's Store app and Back office came from effects. Ask first: "Is this syncing with something outside React?" If not, it should not be an effect at all.

You seeLikely causeFixLesson
Infinite render loop, browser freezesAn effect sets state that is in its own dependency array, or a new object or array in the deps on every renderCompute during render; move the object inside the effect; depend on primitive valuesState and effects
Screen shows stale data from the previous storeMissing dependency, so the effect never re-ranAdd the dependency; turn on the react-hooks/exhaustive-deps lint ruleState and effects
Results for S-014 replaced by results for S-102Race: an older request finished lastIgnore stale responses with a flag or AbortController in the cleanup, or use a data libraryServer data
Effect runs twice in developmentReact Strict Mode mounts, unmounts and mounts again on purposeWrite a cleanup that undoes the effect; do not disable Strict ModeState and effects
Memory leak warning, timers keep firingNo cleanup for an interval, listener or subscriptionReturn a function that clears itState and effects
Input loses focus or state resets on every keystrokeA component defined inside another component, or a changing keyDefine components at module level; keep keys stableComponents
Wrong row updates after deleting from a listArray index used as keyUse a stable id such as the SKU or order idComponents
State change does not showMutated the object or array in placeCreate a new one: [...items, x], { ...order, status }State and effects
Value is one step behind right after setXState updates apply on the next renderUse the value you passed to the setter, or the updater formState and effects
Hydration mismatch warningServer and client render different output (dates, Math.random, window)Render the same on both; move client-only parts into an effectAccessible and fast

A fetch effect done right

Only if you are not using a data library. The cleanup cancels the request when the store changes or the screen closes, so an old answer never overwrites a new one.

TypeScript
useEffect(() => {
  const ctrl = new AbortController();
  setStatus('loading');
  fetch(`/api/stores/${storeId}/stock`, { signal: ctrl.signal })
    .then((r) => { if (!r.ok) throw new Error(`HTTP ${r.status}`); return r.json(); })
    .then((data) => { setStock(data); setStatus('ready'); })
    .catch((e) => { if (e.name !== 'AbortError') setStatus('error'); });
  return () => ctrl.abort();
}, [storeId]);

Server data

Server data is a cache of someone else's state, not your state. A query library (TanStack Query, SWR, or your framework's loader) gives you caching, deduplication, retries and refetch on focus for free (Server data).

I want to...Do thisLesson
Load a list and show loading, error and empty statesA query keyed by everything it depends on, such as ['stock', storeId, page]; render all four statesServer data
Refresh the list after a changeInvalidate that query key after the mutation succeedsServer data
Avoid a spinner flash on fast networksKeep previous data while the next page loads; show a small inline indicatorServer data
Never charge twice on a double tapDisable the button while pending, and send an idempotency key the server checksServer data, Auth and limits
Show moneyKeep integer cents from the API; format only at the edge with Intl.NumberFormatData and money
Type the API responseGenerate types from the OpenAPI spec, or validate with a schema library at the boundaryTypeScript

Forms

Controlled inputs (value plus onChange) suit small forms and live validation. Uncontrolled inputs read with FormData on submit suit long forms. Either way the server validates again: the browser check is for the user, the server check is for safety (Forms).

RuleWhyLesson
Every input has a visible <label> tied by htmlFor and idScreen readers announce it; tapping the label focuses the fieldForms
Use the right type and inputMode (email, tel, inputMode="decimal")Phones show the right keyboardForms
Set autoComplete (name, street-address, one-time-code)Fewer keystrokes, fewer typosForms
Validate on blur and submit, not on every keystrokeErrors do not shout while the user is still typingForms
Put the error next to the field and link it with aria-describedby; move focus to the first errorThe user sees and hears what to fixForms, Accessibility
Keep the user's input after a failed submitRetyping a 12-line Partner app order is how users give upForms
Disable submit only while pending, not while invalidA disabled button gives no reason; an error message doesForms

Accessibility checklist

Run it on every new screen. Most items take minutes when done early and days when done after launch (Accessible and fast, Accessibility).

  • Use real elements: <button> for actions, <a href> for navigation, headings in order, <ul> for lists. A div with onClick is not reachable by keyboard.
  • Everything works with Tab, Shift+Tab, Enter, Space and Escape, and the focus ring stays visible.
  • Images that carry meaning have alt text; decorative ones have alt="". Icon-only buttons have an aria-label.
  • Text contrast at least 4.5:1 (3:1 for large text), per WCAG 2.x AA. Never use colour alone for status; add a word or icon.
  • Touch targets at least 44 by 44 points on iOS and 48 by 48 dp on Android.
  • Dialogs trap focus, close on Escape and return focus to the button that opened them.
  • Announce async results (such as "Order saved") with a live region, aria-live="polite".
  • Respect prefers-reduced-motion and the user's text size; layouts survive 200% zoom.
  • First rule of ARIA: if a native element does the job, use it instead of ARIA.

Performance: if you see X, reach for Y

Measure first with the React DevTools Profiler and the browser Performance panel, on a mid-range phone, not a laptop (Accessible and fast, Performance).

You seeReach for firstThen, if neededLesson
Typing lags in a search boxMove state down so only the box re-rendersuseDeferredValue for the filtered listAccessible and fast
Long list of 25,000 SKUs is slowPaginate or virtualize (render only visible rows)memo on the row componentAccessible and fast
Whole page re-renders on a small changeSplit context; lift content up as childrenmemo with stable propsAccessible and fast
Slow first loadCode-split routes with lazy and Suspense; check bundle sizeServer rendering; drop heavy dependenciesPerformance
Layout jumps as images loadSet image width and heightReserve space for late contentAccessible and fast
Big images on a phoneResponsive sizes and a modern format, lazy load below the foldA CDN that resizes on the flyPerformance

Web vitals worth remembering

Google's "good" thresholds, measured at the 75th percentile of real page loads: Largest Contentful Paint (LCP) 2.5 s or less, Interaction to Next Paint (INP) 200 ms or less, Cumulative Layout Shift (CLS) 0.1 or less. INP replaced First Input Delay in 2024 (Accessible and fast, Performance).

Testing with Testing Library

Test what the user sees and does, not component internals. Query by role first; if you cannot find an element by role and name, a screen reader user cannot either (Testing React, Test and release).

I want to...UseLesson
Find a button, link, heading or inputscreen.getByRole('button', { name: /place order/i })Testing React
Find a form fieldgetByLabelText('Quantity')Testing React
Check something is not therequeryByText(...) returns null instead of throwingTesting React
Wait for something that appears after a fetchawait screen.findByText('Saved')Testing React
Type and click like a userconst user = userEvent.setup(); await user.type(input, '12'); await user.click(btn)Testing React
Fake the APIMock at the network level (for example Mock Service Worker), not by mocking your own hooksTesting React
Last resort selectorgetByTestId; on React Native, testIDTest and release
Test whole flows in a real browserPlaywright end-to-end tests for the few journeys that make moneyPlaywright E2E

React Native: web element to core component

React Native renders native views, not HTML. There is no CSS cascade: styles are JavaScript objects, layout is Flexbox with flexDirection: 'column' as the default, and all text must sit inside <Text> (RN basics).

On the webIn React NativeNotesLesson
<div><View>Flexbox, column by defaultRN basics
<span>, <p><Text>Raw strings outside Text crashRN basics
<img><Image>Network images need a width and heightRN basics
<input><TextInput>onChangeText, keyboardTypeRN basics
<button><Pressable>Add accessibilityRole="button" and a labelRN basics
Scrolling <div><ScrollView>Renders every child; only for short contentMobile performance
A long list<FlatList> or <SectionList>Virtualized; give keyExtractor a stable idMobile performance
localStorageAsyncStorage for small values, SQLite for real data, secure storage for tokensNever keep tokens in plain AsyncStorageOffline first
URL routingA navigator (React Navigation or Expo Router)Stacks, tabs, deep linksNavigation

React Native: "I want to..."

The Mangrove app and the Rider app both run on React Native with Expo. Check which Expo SDK and React Native version a library supports before adding it.

I want to...Do thisLesson
Keep content out of the notch and home indicatorSafe area insets (react-native-safe-area-context)RN basics
Stop the keyboard covering the inputKeyboardAvoidingView and a scroll containerRN basics
Open the app at a product from a linkDeep links with a URL scheme, plus universal links (iOS) and app links (Android)Navigation
Keep the cart when the rider loses signalSave to a local database first, queue writes in an outbox, sync with idempotency keysOffline first
Know if the device is onlineNetInfo, but treat it as a hint; a failed request is the real signalOffline first
Use camera, location or notificationsAsk for permission at the moment of use, explain why, handle "denied" gracefullyDevice features
Scan a barcodeA camera library with barcode scanning; test in bad lightDevice features
Send push notificationsAPNs for iOS, FCM for Android (or Expo's push service on top); store tokens per deviceDevice features
Find what makes a screen jankyProfile in a release build on a cheap Android phone; check the JS and UI frame ratesMobile performance
Ship a JavaScript-only fix fastOver-the-air update (for example EAS Update), within the store rules; native changes need a store releaseTest and release
Roll out a store release safelyStaged rollout on Google Play, phased release on the App Store; watch crash-free sessionsTest and release

Mobile numbers worth remembering

60 frames per second leaves about 16 ms per frame for JavaScript and layout; 120 Hz screens leave about 8 ms. Plan for slow 3G-like networks and phones with 2 to 3 GB of RAM in many markets. A crash-free sessions rate below about 99.5% usually means users notice. Store review can take from hours to a few days, so never plan a launch for the day you submit (Mobile performance, Test and release).

Glossary

Plain definitions of the terms used most in the React and React Native courses.

Component
A function that takes props and returns UI; the building block of every React screen. Components
Props
Read-only inputs a parent passes to a child component. Components
State
Data a component owns that changes over time; changing it re-renders the component. State and effects
Re-render
React calling a component again to work out the new UI, then updating only what changed. State and effects
Hook
A function starting with use that lets a component use React features such as state or effects. State and effects
Effect
Code that runs after render to sync with something outside React, with an optional cleanup. State and effects
Dependency array
The list of values an effect or memo reads; React re-runs it when one of them changes. State and effects
Key
A stable id on each list item that lets React match items between renders. Components
Lifting state up
Moving state to the closest common parent so two children can share it. Components
Context
A way to pass a value deep down the tree without passing props through every level. Components
Controlled input
An input whose value comes from React state and changes only through onChange. Forms
Memoization
Reusing a previous result when inputs have not changed (memo, useMemo, useCallback). Accessible and fast
Suspense
A component that shows a fallback while its children wait for code or data. Server data
Hydration
Attaching React to HTML that was rendered on the server, so the page becomes interactive. Accessible and fast
Optimistic update
Showing the expected result before the server confirms, and undoing it if the request fails. Server data
Cache invalidation
Marking cached server data as stale so it is fetched again. Server data
Strict Mode
A development-only wrapper that runs some code twice to expose missing cleanups and impure renders. State and effects
ARIA
Attributes that tell assistive technology what an element is and its state; a fallback when no native element fits. Accessibility
Virtualized list
A list that renders only the rows on screen, such as React Native's FlatList. Mobile performance
Core components
React Native's built-in native building blocks: View, Text, Image, TextInput, Pressable and lists. RN basics
Expo
A framework and set of services on top of React Native for building, updating and releasing apps. RN basics
Deep link
A URL that opens the app at a specific screen, such as one product. Navigation
Offline-first
Saving to the device first and syncing with the server when the network allows. Offline first
Over-the-air (OTA) update
Shipping a new JavaScript bundle to installed apps without a store release. Test and release
Staged rollout
Releasing a new app version to a growing share of users while watching crash rates. Test and release
Core Web Vitals
Google's three user-experience metrics: LCP for loading, INP for responsiveness, CLS for visual stability. Performance

Courses on Kolom

  • The React documentation at react.dev. Read "You Might Not Need an Effect" and "Thinking in React" first; they prevent most of the bugs in the traps table.
  • The React Native documentation at reactnative.dev, and the Expo docs at docs.expo.dev for builds, updates and device APIs.
  • Testing Library at testing-library.com, especially the guide on which query to use.
  • web.dev at web.dev for Core Web Vitals and how to measure them.
  • MDN Web Docs on accessibility at developer.mozilla.org, and the WCAG quick reference from the W3C.