Does Expo, and React Native in general,Use React Compiler?
Expo and React Native can use React Compiler, but teams should treat it as explicit rollout work: configure Babel, validate plugin order, and measure real device impact.
Short answer: they can, but you should not assume it is active by default in every app. Expo and React Native projects can use React Compiler when versions are compatible and Babel is configured correctly.
The common mistake is confusing support in principle with optimization in practice. You can install the package and still get zero compiler benefits if the transform is not running in your real Metro build path.
What React Compiler is, and what it is not
React Compiler is a build-time optimization pass. It analyzes eligible component code and inserts optimizations that reduce unnecessary rerenders and repeated compute work.
Does React Native use it by default?
Treat the answer as opt-in unless verified. Even when the plugin exists in package.json, it may not be active in Metro output, or it may skip important code paths.
1 Configuration vs installation
Dependency presence only adds capability. Babel wiring is what enables transformation.
2 Ordering matters
Compiler should run early while required-last plugins keep their strict final position.
3 Eligibility matters
Some patterns are intentionally skipped, so observed results can vary across screens.
Expo setup example
Expo apps are React Native apps with managed tooling layers. The same core rule applies: verify that the compiler plugin is in the Babel transform path your app actually uses.
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: [
['babel-plugin-react-compiler', {
compilationMode: 'infer',
panicThreshold: 'none',
}],
// Keep this last when using Reanimated.
'react-native-reanimated/plugin',
],
};
};
The major takeaway is this: Expo can absolutely run React Compiler, but no team should assume it is active without explicit verification.
React Native CLI setup example
module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: [
['babel-plugin-react-compiler', {
compilationMode: 'infer',
panicThreshold: 'none',
}],
// Keep ordering requirements from your stack.
'react-native-reanimated/plugin',
],
};
Whether you are on Expo or RN CLI, ensure local and CI builds share the same config; otherwise your optimization assumptions drift across environments.
Component example: before and after
In many apps, developers preemptively add heavy memoization around filtering and row rendering.
import React, { useCallback, useMemo, useState } from 'react';
import { FlatList, Text, TextInput, View } from 'react-native';
export function ProductSearchScreen({ products }) {
const [query, setQuery] = useState('');
const filtered = useMemo(
() =>
products.filter((p) =>
p.title.toLowerCase().includes(query.toLowerCase())
),
[products, query]
);
const renderItem = useCallback(
({ item }) => <Text>{item.title}</Text>,
[]
);
return (
<View>
<TextInput value={query} onChangeText={setQuery} />
<FlatList data={filtered} keyExtractor={(item) => item.id} renderItem={renderItem} />
</View>
);
}
With compiler enabled and validated, this can often be written more directly and still perform well.
import React, { useState } from 'react';
import { FlatList, Text, TextInput, View } from 'react-native';
export function ProductSearchScreen({ products }) {
const [query, setQuery] = useState('');
const filtered = products.filter((p) =>
p.title.toLowerCase().includes(query.toLowerCase())
);
function renderItem({ item }) {
return <Text>{item.title}</Text>;
}
return (
<View>
<TextInput value={query} onChangeText={setQuery} />
<FlatList data={filtered} keyExtractor={(item) => item.id} renderItem={renderItem} />
</View>
);
}
Directive control for staged rollout
Directives let teams adopt compiler behavior in smaller, controlled steps.
export function StableCard() {
'use memo';
return <Text>Compiled card</Text>;
}
export function LegacyComplexWidget() {
'use no memo';
return <Text>Temporarily excluded from compilation</Text>;
}
Use these directives as migration controls, not long-term defaults. Growing permanent opt-outs usually indicate deeper code-shape issues.
Verification checklist for Expo and RN teams
| Check | What to confirm | Why it matters |
|---|---|---|
| Babel config in effect | Local dev, CI, and EAS use the same intended config | Stale config silently disables transforms |
| Plugin order | Compiler early, strict-last plugins remain last | Wrong order can break or weaken optimization |
| Version compatibility | React, RN, Expo SDK, compiler plugin alignment | Mismatches reduce confidence and predictability |
| Compilation evidence | Logs, transformed output cues, or DevTools indicators | Prevents false confidence from package-only setup |
| Performance evidence | Input latency, list smoothness, navigation responsiveness | Adoption should be justified by user-facing impact |
| Device coverage | Older or lower-tier Android and iOS hardware checks | Mobile bottlenecks appear first on constrained devices |
Where the compiler helps, and where it does not
React Compiler can reduce boilerplate in prop-heavy trees and callback-heavy component paths. It can make performance patterns more consistent and code easier to maintain.
It does not replace FlatList strategy, image handling, network payload discipline, or avoiding expensive work on the JS thread. Those still matter just as much in real React Native performance work.
Bottom line
Expo and React Native can both use React Compiler. But teams should treat compiler adoption as explicit engineering work: configure, verify, and measure.
That expectation is the practical one for production apps. React Compiler is not magic, but when integrated intentionally it can remove memoization noise and improve consistency across complex mobile screens.