Journal

Why Is My AI-Generated React Native App So Slow? (Fixes)

Most slow AI-built React Native apps are not slow because of React Native. They are slow because of five habits the model repeats.

Why Is My AI-Generated React Native App So Slow? (Fixes): a glowing iPhone home-screen icon on a purple and blue gradient

TL;DR

An AI-generated React Native app usually feels slow for five fixable reasons: you are testing a development build, console.log and heavy work are blocking the JavaScript thread, long lists render as ScrollView or unconfigured FlatList, whole screens re-render on every keystroke, and images are oversized. Measure in a release build, move animation to the native driver or Reanimated, switch big lists to FlashList, and memoize what the profiler flags. Starting screens from a VP0 design keeps component trees shallow from the first prompt.

An AI-generated React Native app is almost never slow because of React Native. It is slow because the model repeats a handful of habits: you are testing a development build that is supposed to be slow, console.log calls and heavy work are blocking the JavaScript thread, long lists are rendered all at once, whole screens re-render on every keystroke, and images are downloaded at many times their display size. Each has a known fix, and most take minutes once you have measured which one you have. Prevention helps too: starting screens from a free VP0 design gives the agent a clear, shallow structure to reproduce, so you are not debugging a twelve-level tree of wrapper views later. Here is the diagnosis order that finds the problem fastest.

First, make sure you are measuring the right build

The most common “slow app” is not slow at all; it is a development build. The React Native team is explicit that JavaScript thread performance suffers greatly in dev mode, because the runtime is doing extra work to give you warnings and helpful errors, and it tells you to always test performance in release builds. Expo Go and a dev client both run in development mode by default, so a list that stutters there may be perfectly smooth in the build your users install.

Before changing any code, build a release version and put it on a real device, ideally an older, cheaper phone, since that is where your slowest users are. On Expo, a preview or production profile build via EAS gives you exactly that; on a bare project, run the release configuration. If the lag disappears, you have saved yourself a day. If it remains, you now have an honest baseline, and every fix below can be judged against it. The pre-launch test pass covers the rest of that real-device routine.

Understand the two threads, and why 16.67ms matters

React Native renders on a native main thread while your app logic runs on a JavaScript thread. Phones display at least 60 frames per second, which the documentation translates into a hard budget: at most 16.67ms to produce each frame. If the JavaScript thread misses that budget, touches feel late, navigation transitions stutter, and anything animated through JavaScript jerks.

The developer menu’s Perf Monitor shows both frame rates separately, and that split is your map. A dropping JS frame rate with a steady UI frame rate means your JavaScript is doing too much: logging, parsing, re-rendering, or computing in the middle of an interaction. A dropping UI frame rate points at the native side: too many views, expensive shadows and transparency, or giant images being decoded. Generated code tends to fail on the JS side, which is also the side easiest to fix.

SymptomLikely causeFirst fix to try
Everything feels sluggish in Expo GoDevelopment mode overheadMeasure a release build on a real device
Typing in a field lagsWhole screen re-renders per keystrokeMove input state down, memoize siblings
Long list stutters or shows blanksScrollView or untuned FlatListFlashList, or tune FlatList props
Animations jerk during loadingAnimation driven on the JS threadNative driver or Reanimated
Scrolling a photo grid drops framesFull-size images decoded for thumbnailsRequest sized images, use a caching image component
App is slow only after navigating a whileListeners or intervals never cleaned upReturn cleanup functions from effects

Find the JavaScript thread blockers

Start with the embarrassing one. Agents love logging, and generated code often ships with console.log inside render functions, list items, and network handlers. The React Native docs warn that in a bundled app these statements can cause a big bottleneck in the JavaScript thread, including logging from debugging libraries. Search the project for them, delete what you do not need, and strip the rest from production builds with the Babel plugin the docs recommend.

Next, look for work that happens during interactions. Parsing a large JSON response, sorting thousands of items, or formatting every date in a list on each render all compete with the frame budget. Move heavy computation out of render, compute it once when data arrives, and cache the result. For work that can wait until an animation or transition finishes, defer it rather than racing it.

Animations deserve special attention. The Animated API calculates each frame on the JavaScript thread unless you set useNativeDriver: true, which hands the animation to the native side so it keeps running smoothly even while JavaScript is busy. For gestures and anything more ambitious, Reanimated runs animation logic on the UI thread. Generated code often animates opacity and position through plain state updates; converting those is one of the most visible improvements you can make.

Fix the lists, where most AI apps lose their frames

Lists are where generated apps suffer most, because the model reaches for the simplest thing that renders: a ScrollView with .map() over the whole array. That mounts every row at once, which is fine for ten rows and painful for five hundred. The first fix is to use a virtualized list. The second is to configure it. React Native’s FlatList optimization guide lists the knobs: windowSize defaults to 21, meaning ten viewports above and ten below are kept mounted, and lowering it reduces memory and work at the cost of occasional blank space; getItemLayout removes async layout measurement when rows share a height, which the guide calls a very desirable optimization; and keeping row components light and stable matters as much as any prop.

For long or complex feeds, the bigger win is often switching to FlashList, which keeps props close to FlatList’s but recycles cell components under the hood instead of creating new ones as you scroll. In practice that means fewer blank cells and far less JavaScript work on fast scrolls. It is a small migration and a good task to hand the agent with a precise instruction.

Whichever list you use, give rows a stable keyExtractor, avoid inline arrow functions and inline style objects in renderItem when the profiler shows rows re-rendering, and wrap the row component in React.memo so unchanged rows are skipped. A feed built from a well-structured design with one clear row component is much easier to optimize than one where every row is a bespoke nest of views.

Stop the re-render cascade

The quietest performance killer in generated code is state held too high. A typical agent-written form keeps every field’s value in the screen component, so each keystroke re-renders the whole screen: the header, the image, the list below, all of it. On a fast phone you may not notice; on an older one, typing feels like wading.

The fix is structural rather than clever. Keep state as close as possible to where it is used, so a text input owns its own value until submit. Split large screens into components with clear props, and use React.memo on children that receive the same props most of the time, together with useCallback for functions you pass down, so memoization is not defeated by a new function identity on each render. Do not memoize everything by reflex; React’s own documentation notes that memo is a performance optimization, not a guarantee, and blanket use adds noise. Profile, find the components that render far more than they should, and fix those.

Global state is the other cascade. A single context that holds the user, the cart, the theme, and the current screen re-renders every consumer when any of them changes. Splitting it into smaller contexts, or using a store with selectors, stops a cart update from repainting the settings screen.

Images, memory, and the leaks that build up

Images are the native-side culprit. Agents often request the original photo and let the view scale it down, so a 4,000-pixel photo is decoded to fill a 90-pixel thumbnail, roughly 44x more pixels in each direction than the screen can show. Ask your backend or image CDN for sized variants, and use a caching image component such as expo-image so the same picture is not downloaded and decoded again on every scroll. The FlatList guide makes the same point: every image in a list is a new instance, and the faster it loads, the sooner the JavaScript thread is free again.

Leaks explain the app that is fine at launch and sluggish after ten minutes. Generated effects frequently subscribe to listeners, start intervals, or open sockets without returning a cleanup function, so every visit to a screen adds another one. Search useEffect calls for subscriptions and timers and make sure each returns its cleanup. It is tedious work, and it is exactly the kind of mechanical audit an agent does well once you ask for it explicitly.

Finally, confirm the engine. Hermes is used by default by React Native and improves start-up time, memory use, and app size, so if an older template or a copied config has switched it off, turning it back on is a free improvement. If you are weighing frameworks because of speed, the React Native versus Capacitor comparison explains where each one genuinely wins.

Key takeaways: speeding up an AI-built React Native app

Measure before changing anything: a release build on an older real phone, with the Perf Monitor telling you whether JavaScript or native rendering is dropping frames. Then work down the usual suspects in order: delete logging from hot paths, move animation to the native driver or Reanimated, virtualize and tune long lists or switch them to FlashList, push state down and memoize what the profiler flags, and serve images at the size they are shown. Give the agent the evidence and a precise instruction for each, not a vague request to make it faster. And prevent the next round by starting screens from a free VP0 design, so the component structure the agent writes is shallow and list-friendly from the first prompt.

Frequently asked questions

Why is my AI-generated React Native app so slow? Usually one of five things: you are judging a development build, the JavaScript thread is blocked by logging or heavy work, a long list is rendered with ScrollView or an unconfigured FlatList, screens re-render far more than they should, or images are far larger than they are displayed. Fix those in order, and start new screens from a VP0 design so the agent generates shallow, list-friendly component trees from the beginning.

Is React Native itself too slow for a real app? No. React Native renders native views, and its JavaScript engine, Hermes, is on by default. Plenty of large apps ship on it at a smooth frame rate. When an app is slow, the cause is almost always the code on top of the framework, which is good news, because code can be fixed.

How do I know whether the lag is JavaScript or native? Turn on the Perf Monitor from the developer menu. It shows the JS frame rate and the UI frame rate separately. If the JS number drops while the UI number holds, your JavaScript is doing too much work; if the UI number drops, look at heavy views, shadows, oversized images, or layout.

Should I replace FlatList with FlashList? For long or complex lists, it is often the single biggest win, because FlashList recycles cell components instead of mounting new ones, and its props are close to FlatList’s. For a short list of a dozen rows, a plain map or a tuned FlatList is fine.

Can I ask the AI to fix the performance itself? Yes, if you give it evidence. Paste the profiler output or name the slow screen and the measured frame drop, and ask for specific changes: memoize this row, move this animation to the native driver, switch this list to FlashList. A vague “make it faster” tends to produce churn without a measurable gain.

Other questions VP0 users ask

Why is my AI-generated React Native app so slow?

Usually one of five things: you are judging a development build, the JavaScript thread is blocked by logging or heavy work, a long list is rendered with ScrollView or an unconfigured FlatList, screens re-render far more than they should, or images are far larger than they are displayed. Fix those in order, and start new screens from a VP0 design so the agent generates shallow, list-friendly component trees from the beginning.

Is React Native itself too slow for a real app?

No. React Native renders native views, and its JavaScript engine, Hermes, is on by default. Plenty of large apps ship on it at a smooth frame rate. When an app is slow, the cause is almost always the code on top of the framework, which is good news, because code can be fixed.

How do I know whether the lag is JavaScript or native?

Turn on the Perf Monitor from the developer menu. It shows the JS frame rate and the UI frame rate separately. If the JS number drops while the UI number holds, your JavaScript is doing too much work; if the UI number drops, look at heavy views, shadows, oversized images, or layout.

Should I replace FlatList with FlashList?

For long or complex lists, it is often the single biggest win, because FlashList recycles cell components instead of mounting new ones, and its props are close to FlatList's. For a short list of a dozen rows, a plain map or a tuned FlatList is fine.

Can I ask the AI to fix the performance itself?

Yes, if you give it evidence. Paste the profiler output or name the slow screen and the measured frame drop, and ask for specific changes: memoize this row, move this animation to the native driver, switch this list to FlashList. A vague 'make it faster' tends to produce churn without a measurable gain.

Keep reading

Free React Native App Templates (2026): The Best Ones: a reflective 3D App Store icon on a blue and purple gradient
Guides 10 min read

Free React Native App Templates (2026): The Best Ones

The best free React Native app templates in 2026, from UI Kitten to Rootstrap and Obytes, on the modern Expo stack, plus why a template still needs a design.

Lawrence Arya · June 24, 2026
How to Make a React Native App Look Good (2026): the App Store logo on a glass tile over a blue gradient with bubbles
Guides 10 min read

How to Make a React Native App Look Good (2026)

How to make a React Native app look good: the NativeWind foundation, component libraries, native touches, and the design direction that avoids a generic look.

Lawrence Arya · July 2, 2026
v0 by Vercel mobile app export: from web to a real iOS app: a glass photo icon surrounded by chat, music, heart, camera and shopping app icons on a pastel gradient
Guides 10 min read

v0 by Vercel mobile app export: from web to a real iOS app

v0 by Vercel generates web React, so there is no direct mobile export. Here are the three real paths from a v0 design to an iOS app, and when each fits.

Lawrence Arya · June 10, 2026
Can Cursor Build a Full React Native App From Scratch?: a glass photo icon surrounded by chat, music, heart, camera and shopping app icons on a pastel gradient
Guides 6 min read

Can Cursor Build a Full React Native App From Scratch?

Yes, Cursor can scaffold and build a full React Native app, but it is a coding agent, not a hosted builder. Here is the realistic workflow and where it struggles.

Lawrence Arya · June 2, 2026
How AI App Builders Actually Compile to Native Code: the App Store logo as a glossy glass icon on a purple and blue gradient with floating bubbles
Guides 4 min read

How AI App Builders Actually Compile to Native Code

Are AI app builders really native? Most emit React Native or Expo, a few wrap a web view. Here is what each one ships and how App Store risk changes.

Lawrence Arya · June 1, 2026
21st.dev-Style Live Preview for Mobile App Templates: a glowing iPhone home-screen icon on a purple and blue gradient
Guides 4 min read

21st.dev-Style Live Preview for Mobile App Templates

Want a 21st.dev-style live preview for mobile? Browse VP0 designs that preview live, then run the generated code in Expo for instant fast-refresh.

Lawrence Arya · May 30, 2026