Move to React 19.3 (stable 2026-09-09, additive over 19.2) and turn on React Compiler 1.0 for new code; keep existing useMemo/useCallback as escape hatches (removing them can change the compiler's output). On React Native, React follows the RN line: 19.2 on RN 0.83–0.87, 19.3 only from RN 0.88, still a release candidate.
new project → React 19.3 + React Compiler from day one
enabling the Compiler with thin test coverage → React Compiler pinned to an exact version
React Native app → the React version its RN line ships (19.2 on 0.83–0.87; 19.3 with RN 0.88, see RB-E-RN-VERSIONS)
web data-fetching/SSR → RSC via a meta-framework (RB-E-META-FRAMEWORKS)
RSC on React Native → does not apply (RSC is web-only)
hide a subtree but keep its state → <Activity> (with disciplined effect cleanup)
animated enter/exit/shared-element transitions on the web → <ViewTransition> (DOM-only; not on RN yet)
attach behavior to children with no ref and no wrapper element → Fragment Refs
bundle-size-critical web → Preact (redact, Million, TSRX and Vidact are experimental or beta, not production bets)
Options & tradeoffs
the field considered — and why each one isn’t the default here
option
tradeoff
React 19.3 (current line)
additive over 19.2: graduates <ViewTransition> and Fragment Refs, adds react-dom browser() and Trusted Types passthrough. 19.3.0 (2026-09-09, verified vs npm 2026-09-24). On React Native the React version follows the RN line; see note: REACT ON NATIVE.
React Compiler 1.0 (STABLE)
auto-memoizes, replacing most new useMemo/useCallback; stable since 2025-10-07 and in Meta production (1.0.0, verified vs npm 2026-09-24). Rust port ships via Rspack 2.1's built-in SWC loader, 7–13x the Babel plugin; enable via Babel/SWC/Oxc/Vite-8 plugin.
React Server Components (RSC)
server-rendered components over the Flight protocol; web-only; Server Functions are the mutation path and security-sensitive (RB-E-SECURITY owns the CVEs).
<Activity>
hide a subtree while preserving its state (defer/restore); 100% satisfaction in State-of-React 2025; effects are destroyed and re-created on every toggle, so pair it with effect cleanup (see reading: The hidden cost of React.Activity).
<ViewTransition> / use()
<ViewTransition> is STABLE in 19.3: animates enter/exit/update/share on Transition-marked updates via the browser View Transition API; DOM-ONLY, RN support in progress. use() reads promises/context under Suspense.
Fragment Refs
STABLE in 19.3: a ref on a <Fragment> yields a FragmentInstance over its children as a group (events, focus, observers, scrollIntoView), so you can attach behavior to components that expose no ref without a layout-distorting wrapper <div>.
alternative React runtimes
Preact (small, drop-in-ish) is the production option — 11.0.0 (2026-09-30, verified vs npm + the upgrade guide) is ESM-only and moves defaultProps + px auto-suffixing into preact/compat. @tanstack/redact (0.1.0, 23.3KB vs React's 69.2KB gzipped — 66% smaller; synchronous, not concurrent), Million, TSRX (a JSX successor) and Vidact (a Rust React-subset compiler, 0.2.0-beta) are mostly experimental; see note: ALTERNATIVE RUNTIMES.
Verified notes
React is stable, plural, and compiler-optimized. Stable: the 19.x line only adds. Plural: keep three things apart — the library (concurrent features, both platforms), the protocol (RSC: web and server only, with its own CVE history), and the projections (alternative runtimes, mostly experimental). Compiler-optimized: React Compiler 1.0 is production-ready, so new code drops most manual memoization; existing useMemo/useCallback stay as escape hatches, because removing them can change what the compiler emits.
REACT 19.3 (2026-09-09, verified vs the react.dev release post): two experimental APIs graduated plus three smaller wins. (1) browser() is a first-class react-dom API: use(browser()) opts a component out of server rendering, suspending to the nearest Suspense fallback on the server and rendering normally after hydration; it follows use() rules, so it may sit behind a condition or early return and a hook can opt out only when it lacks initial data (the post's useBrowserQuery example) → retire typeof-window checks and mounted-state useEffect. (2) Trusted Types: React no longer coerces values with '' + value before DOM injection sinks, so TrustedHTML/TrustedScript objects reach the browser and a require-trusted-types-for 'script' CSP works (RB-E-SECURITY). (3) RSC: a Context imported from a 'use client' module can be rendered DIRECTLY by a Server Component; the pass-through Provider wrapper is no longer needed. <ViewTransition> animates on Transition-marked updates (startTransition, Suspense reveal, useDeferredValue), and addTransitionType picks per-cause animations; the post says it only works in the DOM, with React Native support in progress. Fragment Refs expose addEventListener/dispatchEvent (first-level), focus/focusLast/blur (depth-first), observeUsing with an Intersection/ResizeObserver, and getClientRects/scrollIntoView.
REACT ON NATIVE (2026-09-24, verified vs npm peer dependencies + the RN 0.88 RC notes): react-native 0.83.0 peers react ^19.2.0 and 0.84.0–0.87.1 peer ^19.2.3; 0.88.0-rc.1 and rc.2 peer ^19.3.0, and the rc.1 notes say "Sync React 19.3.0 into React Native". 0.88 is still a release candidate (rc.2, 2026-09-22) → 19.3 reaches native on the 0.88 line, not before; the tripwire re-checks this at RN 0.89.
COMPILER RUST PORT (2026-07-06, verified vs the Rspack 2.1 blog): merged into SWC and shipping via Rspack 2.1's built-in SWC loader, 7–13x faster than the Babel version (13.5x on dev, 7.4x on build). Rolldown pulled ITS integration over napi binary size; RB-E-BUILD owns that caveat.
GOVERNANCE (2026-07-16, verified vs react.dev/community/team): React moved to the independent React Foundation (Linux Foundation, Feb 2026; exec director Seth Webster) and the repos moved facebook → react org (corroborated across React Status #464/#478 + TWiR). Work is split into 7 WORKING GROUPS (Server, DOM, Fiber, Docs & Community, Compiler, DevX, React Native), each seated on a Leadership Council that coordinates direction.
ALTERNATIVE RUNTIMES (Vidact verified vs the site + npm 2026-09-24, no independent benchmark read): Vidact is a Rust compiler that turns React-syntax components + hooks into direct DOM updates (components run once; the site claims an 8.1 kB gzipped counter). Unsupported React is a COMPILE ERROR, not a fallback, so it is a deliberate subset; its author reports one production app, grep.codemod.com. @tanstack/redact (0.1.0, 2026-09-30, verified vs GitHub + npm) is "an alternative logical projection of React with 100% API compliancy" — SYNCHRONOUS rendering instead of React's concurrent scheduler (no time-slicing, no priority-based updates, simpler transitions/Suspense), which is also its cost: useOptimistic and useFormStatus are no-ops. 23.3KB vs React 19.3.0's 69.2KB gzipped (66% smaller), microbenchmarks favor it on most scenarios especially state updates; deployed in production on tanstack.com and tannerlinsley.com, which is more real-world mileage than the other experimental runtimes here have. TSRX compiles to React/Preact/Solid. PREACT 11 (2026-09-30 per npm; verified vs the release post and the v11 upgrade guide): the production small runtime took a major. Breaking: ESM-only (.mjs; the CommonJS/UMD bundles are gone, `require('preact')` works only where the runtime supports require(esm)); TypeScript 5.1 minimum; defaultProps and automatic `px` suffixing moved out of core into preact/compat; render()'s third argument and Component.base removed; SuspenseList removed from compat; useRef needs an initial value; useEffect cleanup on unmount runs after paint. New: Hydration 2.0, refs forwarded as plain props, Object.is for hook arguments. → A React app swapped onto Preact through preact/compat keeps most of its behaviour; code written against Preact core directly is what migrates.
RB-E-SECURITY owns the RSC/Server-Function CVEs and Trusted Types; RB-E-META-FRAMEWORKS owns how RSC is productised; RB-E-STATE owns how the Compiler changes store choice; RB-E-RN-VERSIONS owns the RN release line.
HISTORY: 2026-10-08 REOPENED: Preact 11.0.0 stable — ESM-only, TS 5.1+, defaultProps/px suffixing moved to preact/compat. 2026-10-08 CORRECTED: the Aurora Scharff "global hooks" reading (added 2026-10-01) was dropped — the post was unpublished (404, absent from the author's RSS, no Wayback snapshot). 2026-10-01 CORRECTED: @tanstack/redact's figures replaced with verified ones (0.1.0, 23.3KB vs React's 69.2KB gzipped, synchronous not concurrent, useOptimistic/useFormStatus no-ops, production on tanstack.com/tannerlinsley.com) — the prior "~9KB, claims 2-3x" was unverified. 2026-09-24 GAP CLOSED: Vidact added to the experimental runtimes (2nd sighting: TWiR #296 + React Digest #2370); React-on-native ranges verified vs npm peer deps; RN 0.88 status moved to rc.2. 2026-09-21 GAP CLOSED: dated the 19.3-on-native answer — RN 0.88 (RC) is the line that syncs React 19.3.0. 2026-09-10 GAP CLOSED: React 19.3 stable (tripwire fired) — <ViewTransition> + Fragment Refs graduate, browser(), Trusted Types, Context in RSC. 2026-07-16 GAP CLOSED: React Foundation governance — 7 working groups under a Leadership Council. 2026-07-06 GAP CLOSED: React Compiler Rust port merged into SWC, shipping via Rspack 2.1. 2026-06-25 CHALLENGED → SURVIVES: adversarial stress test; caveat applied — don't strip existing memoization when enabling the Compiler.
Canonical reading
Editorial annotations on why each piece matters — the articles themselves are the originals; read them there.
The corpus's cache() coverage (nothing else here or in RB-E-DATA held it): React 19's cache() gives per-render memoization for server-side fetches, and the PRELOAD pattern it enables — fire the cached fetch un-awaited high in the tree so deep Server Components that await the same call hit the memo instead of serializing a waterfall. Pedagogical (mock-data demo, mechanics-focused), and the author's own caveat is the durable half: preloading couples the parent to a child's data needs, so don't scatter it prematurely — use it where a measured waterfall exists. Kept on the advocate pass as the gap-filler, not as a deep architectural reference.
The when-NOT-to caveat behind this entry's <Activity> row: hiding preserves STATE but destroys and re-creates EFFECTS on every toggle — so effect-shaped work (keyboard subscriptions, analytics, listeners) piles up subscription/setState waves each time a hidden RN screen is shown again. Pair <Activity> with disciplined effect cleanup or don't use it for effect-heavy subtrees.
Reframes rendering cost as the dominant hidden bottleneck: React's `render` doesn't just paint — it passes state down, updates context consumers, fires effects, and re-subscribes queries, so ordinary patterns (lift-state-up, effects-for-coordination, `useContext` on a whole value, deps-array callbacks) cascade renders top-down (measured ~10x CPU top-vs-leaf). The React Compiler can't save you when a prop *actually* changes. The prescribed toolkit — `useEffectEvent`/stable event callbacks (no deps-array cascades), imperative APIs over hooks (get-a-value + subscribe instead of re-render), `use-context-selector`, and providing *stable* objects through Context — extends the Erikson rendering guide below into a 'render once' discipline. Vendor angle (pitches Legend State), but the render-model reasoning is framework-agnostic. See RB-E-STATE for the state-architecture half.
The end-to-end explanation of when and why React renders — render vs commit, reconciliation, the cascade to children, memo/useMemo/useCallback, Context behavior. The mental model that makes the React Compiler's auto-memoization comprehensible rather than magic.
How React's reconciler connects to a host environment (the renderer interface), and why React Native Testing Library needed its own renderer. The canonical explanation of React's renderer architecture.
Traces the move from useEffect/React-Query/route-loaders to component-level RSC data fetching, with durable principles: component autonomy, deliberate Suspense boundaries, skeleton co-location. RSC architecture from a recognized educator.
Ten component-design patterns for SSR/hydration, multiple instances, concurrent rendering, portals, view transitions, and tainting (useId, React.cache, taintUniqueValue). A durable component-API mental model from an authoritative author.
Traces React 15's non-interruptible recursive reconciliation to Fiber's linked-list + time-slicing design — the 'why it exists' explainer for concurrent React. First in a React-internals series (key-prop, state-updates, out-of-order streaming also available).
A first-principles walk through Fiber's four phases (trigger/schedule/render/commit), the fiber-node shape, time-slicing, and the bitmask lane-priority system. Durable internals knowledge that survives version churn.
A competing-framework author argues deferred state commits and effect dependency arrays are forced by async UI, not arbitrary — even signal-based frameworks hit the same wall. An unusually credible mental model for React's most-griped-about choices.
The what-does-it-actually-emit explainer the other compiler readings skip: a TodoList compiled into cache-slot code (_c() slots + reference-equality checks — a custom caching system, NOT inserted useMemo/useCallback), dependencies inferred from code FLOW rather than manual arrays, memoization applied where hooks are prohibited (behind early returns), and why identical cached JSX objects stop child re-renders without memo wrappers. Plus a staged adoption path (gradual gating, canary) grounded in Meta/Sanity/Wakelet production numbers. Pairs with the saschb2b retrospective (adoption/bail-outs) — this one is the transformation mechanics.
The composition facet these readings otherwise skip — they explain how React RENDERS, this explains how to SHAPE a component API as an app grows. A production team's four-rung ladder with the named pain that justifies each climb: plain props (where most components should stay) → compound components with slots (when a row sprouts a prop for every shape) → a Composer plus Providers (when the same UI must render data from swappable or deferred sources) → lifted state behind a contract (when state must cross a boundary and the layout should stay pure). The first two rungs use no context at all. Its governing rule is the useful one: an abstraction earns its place by making a CURRENT requirement simpler, never by betting on a future you can't see.
An 18-month retrospective: how auto-memoization retired the missing-dependency bug class, the five patterns where the compiler bails out, and a staged adoption path. The mental model for the compiler era (complements the official release post in sources).
Depth (in-domain rules) is owned by the engineering-principles skill — this entry is selection breadth.
The full explanation
The reviewed long-form essay behind this entry — the why, not a how-to. Also on GitHub.
About React core — the compiler era, RSC, and concurrent features
Diataxis: Explanation. This page builds understanding of where React itself is in 2026
and what that means for how you write it. It is not an API reference (that's react.dev) and
not a rules-of-React linter (that's engineering-principles / ESLint). Read this for the why.
The one shift that reframes everything: stop hand-memoizing
For a decade, "React performance" meant manually wrapping things in useMemo, useCallback,
and React.memo to stop needless re-renders. The React Compiler (1.0, stable since
2025-10-07) inverts that. It analyses your components and inserts memoization for you, more
precisely than humans reliably do — across early returns and conditional branches. So the new
mental model is: write straightforward code and let the compiler memoize; manual useMemo/
useCallback become escape hatches, not defaults. (Verified against the official React
Compiler 1.0 announcement.) Escape hatches, not debris: when you enable the Compiler, keep the
useMemo/useCallback calls you already have — removing them can change the compiler's output
— and pin the exact compiler version if test coverage is thin.
That single change cascades: the old "which state library avoids re-renders" reasoning weakens
(RB-E-STATE), and "where are my missing memos" stops being a routine bug class.
The mental model: React is now stable, plural, and compiler-optimized
Three facts define core React in 2026, and they're easy to conflate:
React-the-library is mature and stable on the 19.x line (19.2 shipped <Activity> and
useEffectEvent; 19.3, stable 2026-09-09, graduated <ViewTransition> and Fragment Refs and
added browser()), and now lives under the independent React
Foundation (Linux Foundation, Feb 2026). Stability is the headline.
React-the-protocol (RSC). React Server Components are a server rendering model over the
Flight wire protocol. This is a web concern delivered through meta-frameworks
(RB-E-META-FRAMEWORKS); it does not apply to React Native, and its security issues are
server-side (below, RB-E-SECURITY).
React-the-projection (alternative runtimes). Preact, the experimental @tanstack/redact,
Million, the JSX-successor TSRX, and the Rust React-subset compiler Vidact (0.2.0-beta) are other ways to run React-shaped code. Mostly
experimental; interesting, not production defaults.
Keeping these three apart is most of "understanding modern React."
The default, and why
Move to React 19.3 (additive over 19.2) and turn on React Compiler 1.0 for new code —
let it handle memoization, and keep existing useMemo/useCallback as escape hatches.
This is the low-regret baseline: you're on the stable line, you get the concurrent features,
and you delete a category of manual-memo busywork (and the bugs that come with getting it
wrong). New projects should adopt the Compiler from day one; existing apps can enable it
incrementally. On the web, reach for RSC via a meta-framework when you actually need
server rendering/data; on React Native, RSC simply doesn't apply.
On React Native, the React version follows the RN line (verified 2026-09-24 against npm peer
dependencies and the RN 0.88 RC notes): RN 0.83–0.87 run React 19.2; React 19.3 arrives with RN
0.88, which is still a release candidate (rc.2, 2026-09-22). <ViewTransition> is DOM-only for
now, so the 19.3 headline feature does not reach native even there.
The landscape, and when each piece earns its place
React Compiler 1.0 — on by default for new code; production-proven at Meta. The Rust port
has landed in SWC and ships through Rspack 2.1's built-in SWC loader (7–13x faster than the
Babel plugin). Enable via the Babel/SWC/Oxc/Vite plugin
(RB-E-BUILD).
RSC + Server Functions — server-rendered components and the mutation path. Web-only,
meta-framework-delivered, security-sensitive (RB-E-SECURITY). Use when the server is part of
your architecture, not as a reflex.
Concurrent features — <Activity> (hide a subtree while preserving its state — high
satisfaction in State-of-React 2025), useEffectEvent (read latest values without re-subscribing
effects), use() (read promises/context under Suspense), <ViewTransition> (animated
transitions, stable in 19.3, DOM-only), Fragment Refs (stable in 19.3: attach events, focus and
observers to a group of children without a wrapper element). <Activity> destroys and
re-creates effects on every toggle, so pair it with effect cleanup. Reach for them when the problem matches; they're tools, not obligations.
Alternative runtimes — Preact for bundle-size-critical web; treat @tanstack/redact,
Million, TSRX, and Vidact as experiments, not production bets. The decade of React libraries is the
reason to stay on React unless a concrete driver pushes you off (RB-E-ALT-FRAMEWORKS).
Tradeoffs and failure modes to name out loud
Mutating objects you got from useState defeats the Compiler. The ecosystem's load-
bearing caveat: prefer immutable updates and plain data over behaviour-rich class instances in
render paths, or you fight the optimizer (RB-E-STATE).
Hand-memoizing by default in the compiler era. Adding useMemo/useCallback everywhere
is now noise — and occasionally counterproductive. Let the compiler work; reach for manual
memo only for measured, specific cases. The mirror-image mistake is stripping the memoization
you already have when you enable it.
Treating RSC as universal. RSC/Server Functions are web + server. Assuming they apply to
React Native, or that their CVEs affect RN, is a category error (RB-E-SECURITY).
Chasing experimental runtimes. Betting production on redact/Million/TSRX/Vidact trades a vast,
battle-tested ecosystem for unproven speed claims.
How it interacts with the rest of the stack
State (RB-E-STATE). The Compiler changes the perf calculus — choose a store for its
sharing model and ergonomics, not as a memoisation workaround.
Meta-frameworks (RB-E-META-FRAMEWORKS). RSC/Server Functions are productised there; this
entry is the primitive, that one is the frameworks.
Security (RB-E-SECURITY). The RSC/Server-Function DoS family is server-side and patched
in React 19.0.5/19.1.6/19.2.5; it does not affect React Native.
Build (RB-E-BUILD). The Compiler is a build plugin; how you enable it depends on your
bundler/toolchain.
Rendering depth. When you do need to reason about renders, the depth (render vs commit,
reconciliation, Fiber) lives in the reading and in engineering-principles, not in this page.
In one paragraph
Modern React is stable, plural, and compiler-optimized: move to 19.3 (on React Native,
the version your RN line ships — 19.2 until RN 0.88) and turn on the React Compiler so you stop hand-writing useMemo/useCallback (just don't mutate state
objects and defeat it). Keep the three Reacts straight — the library (stable, concurrent
features), the protocol (RSC: web + server only, not RN, security-sensitive), and the projections
(Preact/redact/Million/TSRX/Vidact: mostly experimental). Reach for RSC and concurrent features when the
problem calls for them, and stay on React for its ecosystem unless a concrete driver pushes you
off.
See also: RB-E-STATE (Compiler changes the state-perf calculus), RB-E-META-FRAMEWORKS
(RSC/Server Functions productised), RB-E-SECURITY (RSC CVEs are server-side), RB-E-TYPESCRIPT.
Rendering/architecture depth: the engineering-principles skill.