Skip to content

React Compiler

React Compiler is a build-time tool that memoizes your components and hooks automatically. The starter enables it by default, so components only re-render when the values they use actually change, without manual useMemo, useCallback or React.memo.

Two pieces turn the compiler on:

  • babel-plugin-react-compiler in devDependencies, installed with bunx expo install so its version matches the Expo SDK
  • experiments.reactCompiler in app.config.ts:
app.config.ts
experiments: {
typedRoutes: true,
reactCompiler: true,
},

babel-preset-expo picks up the setting and runs the compiler on your source code. There is nothing else to configure.

Skip manual memoization. The compiler already memoizes values, callbacks and JSX. Write plain components:

// Before: manual memoization
const filtered = React.useMemo(() => posts.filter(p => p.published), [posts]);
const onPress = React.useCallback(() => open(id), [id]);
// With React Compiler: write it plainly
const filtered = posts.filter(p => p.published);
const onPress = () => open(id);

Existing useMemo and useCallback calls keep working, so you do not have to remove them. Only add new ones when profiling shows a specific need, for example when a third-party library requires a stable reference that the compiler cannot see.

Follow the Rules of React. The compiler assumes your components follow the Rules of React: components and hooks are pure, props and state are not mutated, and hooks are called unconditionally. When a component breaks a rule, the compiler skips it and leaves it unoptimized instead of breaking it.

eslint-plugin-react-hooks v7, included through the starter’s ESLint config, contains the compiler’s diagnostic rules. Code the compiler cannot optimize, such as reading a ref during render or mutating a value, shows up as a lint error. Keep bun run lint clean and the compiler can optimize every component.

Open React Native DevTools from the dev menu and switch to the Components tab. Components optimized by the compiler show a Memo ✨ badge next to their name.

If a component misbehaves with the compiler, add the "use no memo" directive at the top of the component to skip it, then fix the underlying rule violation:

function LegacyChart() {
'use no memo';
// ...
}

Use this as a temporary escape hatch, not a permanent fix.

To turn the compiler off for the whole app, remove reactCompiler: true from app.config.ts and restart Metro with a cleared cache:

Terminal window
bun start -c