The compilationMode option controls how the React Compiler selects which functions to compile.
Reference
Section titled “Reference”compilationMode
Section titled “compilationMode”Controls the strategy for determining which functions the React Compiler will optimize.
'infer' | 'syntax' | 'annotation' | 'all'Default value
Section titled “Default value”'infer'
Options
Section titled “Options”-
'infer'(default): The compiler uses intelligent heuristics to identify React components and hooks:- Functions explicitly annotated with
"use memo"directive - Functions that are named like components (PascalCase) or hooks (
useprefix) AND create JSX and/or call other hooks
- Functions explicitly annotated with
-
'annotation': Only compile functions explicitly marked with the"use memo"directive. Ideal for incremental adoption. -
'syntax': Only compile components and hooks that use Flow’s component and hook syntax. -
'all': Compile all top-level functions. Not recommended as it may compile non-React functions.
Caveats
Section titled “Caveats”- The
'infer'mode requires functions to follow React naming conventions to be detected - Using
'all'mode may negatively impact performance by compiling utility functions - The
'syntax'mode requires Flow and won’t work with TypeScript - Regardless of mode, functions with
"use no memo"directive are always skipped
Default inference mode
Section titled “Default inference mode”The default 'infer' mode works well for most codebases that follow React conventions:
With this mode, these functions will be compiled:
// ✅ Compiled: Named like a component + returns JSXfunction Button(props) { return <button>{props.label}</button>;}
// ✅ Compiled: Named like a hook + calls hooksfunction useCounter() { const [count, setCount] = useState(0); return [count, setCount];}
// ✅ Compiled: Explicit directivefunction expensiveCalculation(data) { "use memo"; return data.reduce(/* ... */);}
// ❌ Not compiled: Not a component/hook patternfunction calculateTotal(items) { return items.reduce((a, b) => a + b, 0);}Incremental adoption with annotation mode
Section titled “Incremental adoption with annotation mode”For gradual migration, use 'annotation' mode to only compile marked functions:
Then explicitly mark functions to compile:
// Only this function will be compiledfunction ExpensiveList(props) { "use memo"; return ( <ul> {props.items.map(item => ( <li key={item.id}>{item.name}</li> ))} </ul> );}
// This won't be compiled without the directivefunction NormalComponent(props) { return <div>{props.content}</div>;}Using Flow syntax mode
Section titled “Using Flow syntax mode”If your codebase uses Flow instead of TypeScript:
Then use Flow’s component syntax:
// Compiled: Flow component syntaxcomponent Button(label: string) { return <button>{label}</button>;}
// Compiled: Flow hook syntaxhook useCounter(initial: number) { const [count, setCount] = useState(initial); return [count, setCount];}
// Not compiled: Regular function syntaxfunction helper(data) { return process(data);}Opting out specific functions
Section titled “Opting out specific functions”Regardless of compilation mode, use "use no memo" to skip compilation:
function ComponentWithSideEffects() { "use no memo"; // Prevent compilation
// This component has side effects that shouldn't be memoized logToAnalytics('component_rendered');
return <div>Content</div>;}Troubleshooting
Section titled “Troubleshooting”Component not being compiled in infer mode
Section titled “Component not being compiled in infer mode”In 'infer' mode, ensure your component follows React conventions:
// ❌ Won't be compiled: lowercase namefunction button(props) { return <button>{props.label}</button>;}
// ✅ Will be compiled: PascalCase namefunction Button(props) { return <button>{props.label}</button>;}
// ❌ Won't be compiled: doesn't create JSX or call hooksfunction useData() { return window.localStorage.getItem('data');}
// ✅ Will be compiled: calls a hookfunction useData() { const [data] = useState(() => window.localStorage.getItem('data')); return data;}