RORK LABJP
DEADLINE — From August 31, every new app and update on Google Play must target Android 16 (API level 36). Seven days to goEXTENSION — If you qualify, you can request an extension through November 1 using a form in Play Console, but the request itself has to be filed before the deadlineMAX — Rork Max generates native Swift rather than React Native and compiles on a cloud Mac fleet, covering iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and iMessageCOMPANION — The Rork Companion app lets you test on a real iPhone without a paid Apple Developer account, so design, build, and test can all happen in a browserDEVTOOLS — React Native DevTools in Expo SDK 57 can emulate light and dark mode, letting you check both appearances without touching device settingsIOS27 — iOS 27 ships next month. Beta 6 landed on August 17, and RCS Universal Profile 3.0 support means you can finally reply to a specific message received from AndroidDEADLINE — From August 31, every new app and update on Google Play must target Android 16 (API level 36). Seven days to goEXTENSION — If you qualify, you can request an extension through November 1 using a form in Play Console, but the request itself has to be filed before the deadlineMAX — Rork Max generates native Swift rather than React Native and compiles on a cloud Mac fleet, covering iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and iMessageCOMPANION — The Rork Companion app lets you test on a real iPhone without a paid Apple Developer account, so design, build, and test can all happen in a browserDEVTOOLS — React Native DevTools in Expo SDK 57 can emulate light and dark mode, letting you check both appearances without touching device settingsIOS27 — iOS 27 ships next month. Beta 6 landed on August 17, and RCS Universal Profile 3.0 support means you can finally reply to a specific message received from Android
Articles/Dev Tools
Dev Tools/2026-07-10Advanced

Adding React Compiler to Expo Let Me Delete 41 Hand-Written memo Calls

I enabled React Compiler on Rork-generated React Native screens and measured the rerender counts with Profiler. Here is how I decided which memo and useCallback calls were safe to delete, how to find the components the compiler bailed out on, and how to catch regressions in CI.

React CompilerExpo182React Native231Performance25Rork543

Premium Article

Tapping the favorite button on a single thumbnail made the whole wallpaper grid flicker. I opened the Profiler and found that all 24 visible cells had rerendered. Exactly one cell had changed.

The cause was not mysterious. The onToggleFavorite handler that Rork had generated was recreated on every render, which rebuilt the entire renderItem for the FlatList.

So I did what everyone does. Wrap it in useCallback. Wrap the cell in React.memo. Stare at the dependency array. I have lost count of how many times I repeated that ritual across six apps. If I am honest, I have introduced more "this screen stopped updating" bugs through mistaken dependency arrays than I ever gained in milliseconds.

That fatigue is why I finally sat down with React Compiler.

What I Actually Tested

The subject is one of the wallpaper apps I run as a solo developer. Three React Native screens built on Expo — grid, detail, settings — originally generated by Rork. Between them they contained 63 hand-written React.memo, useCallback, and useMemo calls.

I wanted answers to three questions.

  1. With React Compiler enabled, how much do rerender counts actually drop?
  2. Are the hand-written memo calls safe to delete? Where does deleting them make things slower?
  3. Can I find the components the compiler gave up on mechanically, rather than by reading every file?

The short version: rerenders on the main interaction dropped from 24 to 2, I deleted 41 of the 63 memo calls, and the remaining 22 each had a concrete reason to stay.

Setup Is One Babel Line, With Two Preconditions

Turning it on in Expo is brief.

npx expo install babel-plugin-react-compiler
// babel.config.js
module.exports = function (api) {
  api.cache(true);
  return {
    presets: [["babel-preset-expo", { "react-compiler": true }]],
  };
};

Passing react-compiler: true to babel-preset-expo lets the preset wire everything up. If you instead add the plugin to plugins by hand, you can end up applying it twice alongside the preset's React Native specific adjustments. I broke a build exactly this way once. Go through the preset.

Two preconditions matter.

Precondition 1: New Architecture must be on. The compiler technically runs on the old architecture, but the rendering behavior it assumes — automatic batching, the re-entrancy that Concurrent rendering brings — only lines up under New Architecture. With the old architecture still in place, the rerender count that should have fallen to 2 stalled at 5. My staged migration notes are in the New Architecture migration writeup.

Precondition 2: Clear the Metro cache. Without npx expo start --clear, you keep serving the pre-transform bundle. Most "I enabled it and nothing changed" reports are this. I covered Metro's caching quirks separately in the Fast Refresh troubleshooting notes.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
A reproducible way to measure rerender counts before and after enabling React Compiler
Clear criteria for which hand-written memo and useCallback calls are safe to remove and which are not
How to find components the compiler silently bailed out on, using ESLint and build output rather than eyeballing
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

Related Articles

Dev Tools2026-08-22
Every bulk replace exited zero. The damage was in the lines I did not delete
Run a bulk replace over generated code and the breakage lands on the neighbouring lines, not the matched ones. Here is what broke in a live project, and a dependency-free guard that checks the invariants a replace must preserve.
Dev Tools2026-08-02
When Two-Character Queries Silently Return Nothing: Measuring Japanese Search Indexes in an Expo App
SQLite FTS5's trigram tokenizer returns zero rows for Japanese queries shorter than three characters, without raising anything. I benchmarked linear scan, a bigram inverted index, and FTS5 over a 20,000-item catalog to find the real threshold.
Dev Tools2026-07-30
What Renovate may bump in an Expo app, and what it must never touch
Turning on automated dependency updates in a Rork-generated app also hands Renovate the 123 packages Expo SDK 57 pins. Measured on 2026-07-30, six of them sit a full major version behind npm latest. Here is how to generate the ignore list from the SDK instead of maintaining it by hand.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →