From FlashList to Reanimated, here are the techniques we use to ship buttery-smooth React Native apps that feel truly native.
A janky list or a laggy animation is the fastest way to make a React Native app feel cheap. After shipping several apps to thousands of users, here are the techniques that consistently make the biggest difference.
- Use FlashList instead of FlatList for any list with more than a handful of items — it recycles views far more efficiently.
- Animate with Reanimated and run gestures on the UI thread via react-native-gesture-handler, never the JS thread.
- Memoize list item components with React.memo and stable callback references to avoid unnecessary re-renders.
- Use InteractionManager or requestAnimationFrame to defer expensive work until after animations complete.
- Optimize images: use the right resolution, prefer WebP, and use a caching image component like expo-image.
- Avoid inline styles and anonymous functions inside render — they create new objects on every render.
- Enable Hermes (on by default in modern Expo/React Native) for faster startup and lower memory usage.
- Profile with Flipper or the React Native DevTools before optimizing — measure, don't guess.
- Batch state updates and avoid storing large objects in frequently-updated state.
- Lazy-load screens and heavy dependencies with React.lazy and dynamic imports where supported.
None of these are exotic — they're disciplined application of fundamentals. The apps that feel 'native' are usually the ones where the team treated performance as a feature from day one, not a cleanup pass at the end.
