GenesisTools gt:react-compiler-debug
Debug and inspect React Compiler (babel-plugin-react-compiler) output. Use when user asks to see what React Compiler generates, debug memoization issues, understand why a component isn't being optimized, or compare original vs compiled code. Triggers on "react compiler", "compiler output", "see compiled", "memoization debug", "why isn't this memoized".
git clone https://github.com/genesiscz/GenesisTools
T=$(mktemp -d) && git clone --depth=1 https://github.com/genesiscz/GenesisTools "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/genesis-tools/skills/react-compiler-debug" ~/.claude/skills/genesiscz-genesistools-gt-react-compiler-debug && rm -rf "$T"
plugins/genesis-tools/skills/react-compiler-debug/SKILL.mdReact Compiler Debug
Inspect what
babel-plugin-react-compiler generates from React components.
Prerequisites
This tool requires GenesisTools to be fully installed (not just the plugin).
If you see
Cannot find package 'babel-plugin-react-compiler':
# Check if tools command exists which tools # If not found, use /gt:setup to install the full toolkit
The
command must be in your PATH for this to work. The plugin alone doesn't include the babel dependencies.tools
Quick Start
# Compile a file and see output tools react-compiler-debug <file.tsx> # Compile inline code tools react-compiler-debug --code "const Foo = ({ x }) => <div>{x}</div>" # Verbose mode (shows compiler events) tools react-compiler-debug -v <file.tsx> # Output to clipboard tools react-compiler-debug <file.tsx> --clipboard # Show original + compiled (for file input only) tools react-compiler-debug <file.tsx> --with-original
Tip for skill usage: When compiling a file and you haven't already read its content, use
to see both the original and compiled versions. This flag is ignored for--with-originalinput.--code
When to Use
- Debug memoization: See if/how React Compiler optimizes a component
- Compare output: Understand the transformation applied
- Diagnose issues: Find why a component isn't being optimized
- Learn: Understand what useMemoCache and other compiler primitives do
Compiler Options Reference
Key options from
babel-plugin-react-compiler:
| Option | Values | Description |
|---|---|---|
| (default), , , | Which functions to compile |
| , , | React version target |
| (default), , | Error handling |
Reading the Output
The compiled output uses React Compiler primitives:
- Creates a cache with n slotsuseMemoCache(n)
,$[0]
, etc. - Cache slot access$[1]
- Cache invalidation markerSymbol.for("react.memo_cache_sentinel")
Example
Input:
const Greeting = ({ name }) => <h1>Hello, {name}!</h1>;
Output (simplified):
function Greeting(t0) { const $ = useMemoCache(2); const { name } = t0; let t1; if ($[0] !== name) { t1 = <h1>Hello, {name}!</h1>; $[0] = name; $[1] = t1; } else { t1 = $[1]; } return t1; }
The compiler memoizes the JSX based on
name prop changes.
Common Bail-out Patterns
When the compiler skips optimization, check for these common causes:
| Pattern | Why it bails out | Fix |
|---|---|---|
| Mutable ref in render | is validated by | Move to or event handler |
| setState in render | during render validated by | Move to event handler or |
| JSX inside try/catch | errors — use error boundaries instead | Wrap component in , remove try/catch |
without | Lowering TODO — compiler can't build HIR for incomplete try | Add explicit block |
| Lowering TODO — finalizer clause not yet supported | Restructure to or extract to utility |
inside try/catch | Lowering TODO — ThrowStatement in try/catch not handled | Extract throwing logic to a separate function |
Inline declaration | — class inside component not supported | Move class outside component/hook |
loops | Lowering TODO — async iteration not yet supported | Use or manual iteration |
statement | — deprecated JS syntax | Remove , use explicit property access |
Debugging tip: Add
at the top of a function body to temporarily opt it out of compilation and confirm the compiler is involved in an issue. Source: BuildHIR.ts, ValidateNoJSXInTryStatement.ts"use no memo"