The compilationMode option controls how the React Compiler selects which functions to compile.
{
compilationMode: 'infer' // or 'annotation', 'syntax', 'all'
} compilationMode
Controls the strategy for determining which functions the React Compiler will optimize.
'infer' | 'syntax' | 'annotation' | 'all' 'infer'
'infer' (default): The compiler uses intelligent heuristics to identify React components and hooks:
"use memo" directiveuse prefix) AND create JSX and/or call other hooks'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.
'infer' mode requires functions to follow React naming conventions to be detected'all' mode may negatively impact performance by compiling utility functions'syntax' mode requires Flow and won’t work with TypeScript"use no memo" directive are always skippedThe default 'infer' mode works well for most codebases that follow React conventions:
{
compilationMode: 'infer'
} With this mode, these functions will be compiled:
// ✅ Compiled: Named like a component + returns JSX
function Button(props) {
return <button>{props.label}</button>;
}
// ✅ Compiled: Named like a hook + calls hooks
function useCounter() {
const [count, setCount] = useState(0);
return [count, setCount];
}
// ✅ Compiled: Explicit directive
function expensiveCalculation(data) {
"use memo";
return data.reduce(/* ... */);
}
// ❌ Not compiled: Not a component/hook pattern
function calculateTotal(items) {
return items.reduce((a, b) => a + b, 0);
} For gradual migration, use 'annotation' mode to only compile marked functions:
{
compilationMode: 'annotation'
} Then explicitly mark functions to compile:
// Only this function will be compiled
function 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 directive
function NormalComponent(props) {
return <div>{props.content}</div>;
} If your codebase uses Flow instead of TypeScript:
{
compilationMode: 'syntax'
} Then use Flow’s component syntax:
// Compiled: Flow component syntax
component Button(label: string) {
return <button>{label}</button>;
}
// Compiled: Flow hook syntax
hook useCounter(initial: number) {
const [count, setCount] = useState(initial);
return [count, setCount];
}
// Not compiled: Regular function syntax
function helper(data) {
return process(data);
} 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>;
} In 'infer' mode, ensure your component follows React conventions:
// ❌ Won't be compiled: lowercase name
function button(props) {
return <button>{props.label}</button>;
}
// ✅ Will be compiled: PascalCase name
function Button(props) {
return <button>{props.label}</button>;
}
// ❌ Won't be compiled: doesn't create JSX or call hooks
function useData() {
return window.localStorage.getItem('data');
}
// ✅ Will be compiled: calls a hook
function useData() {
const [data] = useState(() => window.localStorage.getItem('data'));
return data;
}
© 2013–present Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://react.dev/reference/react-compiler/compilationMode