Most production issues aren’t missing features,they’re avoidable mistakes. Here are the pitfalls I see most often and the fixes that have worked across my projects.
1) Overloading the JavaScript thread
Heavy compute (image processing, big JSON parsing) on the JS thread blocks touch handling and UI updates, causing jank.
- Move heavy tasks to native modules or background workers.
- Prefer
react-native-reanimatedfor animations (runs on native/UI thread). - Defer non-critical work; schedule after interactions.
In a voice assistant app, shifting audio encoding to native eliminated UI freezes on low-end devices.
2) Misusing FlatList
FlatList “just scrolling” is a myth,poor setup leads to lag and crashes.
- Provide stable
keyExtractor. - Use
getItemLayoutwhen rows are fixed height. - Memoize row components; avoid inline functions inside
renderItem.
After applying these in a marketplace list of 100s of items, scroll stutter dropped noticeably on mid-tier phones.
3) Forgetting to clean up listeners
Keyboard/AppState/sockets without cleanup leak memory and create odd behavior.
- Always return a cleanup function in
useEffect. - Unsubscribe global listeners on unmount.
4) Shipping debug logs to production
console.log adds JS-thread overhead in prod.
- Strip logs with
babel-plugin-transform-remove-consolein production builds. - Remove dev-only code paths before release.
5) Staying on the legacy bridge
Ignoring JSI/TurboModules/Fabric keeps latency high and limits modern libraries.
- Prefer libraries compatible with the New Architecture.
- Migrate hot paths (heavy animations, data-heavy screens) first; test cross-platform.
6) Inconsistent styling and excessive inline styles
Inline objects are recreated every render; scattered styles hurt consistency.
- Use
StyleSheet.create(). - Centralize theme tokens (colors, spacing, fonts).
- Adopt a design system or theming library.
7) State management that triggers wide re-renders
Putting everything in global state or lifting too high causes unnecessary updates.
- Keep state local where possible; split UI into smaller memoized parts.
- Use
useMemo,useCallback, andReact.memodeliberately. - Choose state tools (Redux, Zustand, Jotai) based on change patterns,not habit.
8) Ignoring platform differences
Android/iOS differ in keyboard, gestures, back behavior, safe areas, and UI norms.
- Test on both platforms frequently.
- Use
Platform.select()for small divergences and platform-specific files when needed.
Closing thoughts
Production quality comes from discipline: protect the JS thread, configure lists correctly, clean up subscriptions, adopt the new architecture, keep styles consistent, manage state surgically, and respect platform differences. Spot the worst offender in your app and fix it first,compounding gains follow.