Sascha Becker

Sascha Becker

WorkProjectsAIBlogContact
Contact

Copyright © 2026 Sascha Becker

Legal Notice
All skills↗
Engineering
  • Storybook Pentest
  • Comment Stinky
  • Test Stinky
  • Tauri Stinky
  • React Stinky
  • Visual Consistency
  • Open Design System Format (ODSF)
  • Build and maintain an MCP server
  • Godot Development
  • Android Development with Compose and Material 3 Expressive
  • JavaScript Ecosystem
  • Theme Colors
  • Audit pull_request_target
  • Typesafe API Codegen
  • React Compiler
  • Open Knowledge Format (OKF)
  • Trust Card
Productivity
  • Game Design
  • Write Without the Slop
  • Fable Mode
  • Breadcrumbs
  • Autopilot
  • Questions Before Pixels
  • Stories, Not Braindumps
  1. AI
  2. /
  3. Skills
  4. /
  5. React Compiler

Engineering / react-compiler

React Compiler

Write and review React code as if the React Compiler is enabled.

  • #frontend
  • #react
  • #review

Install

$npx skills@latest add saschb2b/skills --skill react-compiler
View on GitHub ↗·Read the post →
Trust card

Trust you can verify yourself

7/13uncommonexecutable-L1

Signed, graded provenance for this skill. Integrity, authorship, capability, and freshness as evidence you weigh, not a verified badge.

Trust layers
Provenance
bydid:web:saschb2b.com
digest
expires2027-07-27
Verify it yourself
$python scripts/card.py verify skills/engineering/react-compiler/CARD.md --bundle skills/engineering/react-compiler
CARD.md/trust-card →

Rule

The compiler memoizes. You do not.

In any React 19+ codebase with the compiler enabled, do not add useMemo, useCallback, or React.memo by default. The compiler handles memoization at finer granularity than a human writes, and adding manual versions is at best noise. This is the most common failure mode in LLM-generated React: the bulk of any agent's React training corpus is pre-compiler, so the default output skews toward manual memoization.

Default behavior when writing React

Write components plainly:

tsx
function DashboardRow({ entity, onSelect }) {
const label = formatLabel(entity);
const total = entity.items.reduce((sum, i) => sum + i.value, 0);
return (
<Row onClick={() => onSelect(entity.id)}>
<Label>{label}</Label>
<Total>{total}</Total>
</Row>
);
}

Not:

tsx
const DashboardRow = memo(({ entity, onSelect }) => {
const formatted = useMemo(() => ({ /* ... */ }), [entity]);
const handleClick = useCallback(() => onSelect(entity.id), [entity.id, onSelect]);
return /* ... */;
});

The compiler produces the equivalent of the first from any input that follows the Rules of React. Adding the second by hand is noise and can interfere with the compiler's analysis.

Three exceptions where manual memoization is still required

Keep manual useMemo or useCallback only in these cases:

  1. Referential identity for non-React consumers. Values feeding into addEventListener, an IntersectionObserver, third-party libraries with their own === checks, anything outside React that retains the reference.
  2. Expensive non-render work the compiler cannot see through. Parsing a large blob, building a large index, calling a heavy library. Keep, and add a comment explaining why.
  3. Effect dependencies that must be stable for correctness. If a dependency would trip the effect every render without the wrap, keep it.

Anything outside these three cases gets deleted.

Audit workflow on an existing codebase

  1. Confirm compiler is enabled. Check next.config (experimental.reactCompiler), vite.config or babel.config (babel-plugin-react-compiler), or framework defaults for Expo and TanStack Start. If not enabled, propose enabling first. Do not strip memoization on a compiler-off codebase.
  2. Confirm eslint-plugin-react-hooks is at v6+. The compiler rules merged in from the deprecated eslint-plugin-react-compiler in late 2025.
  3. Promote lint rules to error. recommended ships most at warn, which means CI does not fail on silent compiler skips. See lint-setup.md for the strict configuration.
  4. Sweep manual memoization. Delete useMemo, useCallback, React.memo that do not match one of the three exceptions.
  5. Run lint. Fix silent skips iteratively. Silent skips cascade: fixing an upstream skip can reveal a second issue downstream. First run gives the count. Subsequent runs give the truth.
  6. Track "use no memo" directives. Each is a performance cliff with a TODO behind it. Grep the count over time as a health metric.

When the compiler silently bails

Five patterns drop the surrounding function out of compilation. The lint rules above catch them when configured strictly. Full list, code examples, and fixes in exceptions.md.

Output format for an audit

file: <path>
findings:
- removed: <useMemo | useCallback | memo> @ <line>, compiler handles
- kept: <useMemo | useCallback> @ <line>, reason: <ref-identity | expensive | effect-dep>
silent bails detected:
- <pattern> @ <line>: <one-line fix>

Source

Based on The React Compiler at Eighteen Months. Sibling detail in exceptions.md and lint-setup.md.


← Previous

Typesafe API Codegen

Next →

Open Knowledge Format (OKF)

English