React Native performance tips
React Native performance tips¶
Watch a video of the techniques presented in this post
Performance Monitoring¶
Should measure on release builds, dev builds are not always a great indication of performance with logging etc
Tools¶
iOS Simulator Perf Monitor¶
ctrl+cmd+z → Show Perf Monitor

npx react-devtools¶

Should Render state
Naming your components properly for the Flamegraph
Notice we can’t tell what this component is very easily, which has the definition of
export const Toolbar: FC<ToolbarBaseProps> = observer(
({ *id*, *entityType*, *config*, *containerTestId* }) => {

If we rewrite this definition with a function name, we can now see that this is obviously the Toolbar
export const Toolbar: FC<ToolbarBaseProps> = observer(function Toolbar({
id,
entityType,
config,
containerTestId,
}) {

Profiler settings
Record why each component rendered while profiling
Hide commits below Xms
Reading the Flamegraph
Commits are relative, yellow is longer rendering time but doesn’t mean it’s bad
But, consider the component it is. If it’s a slowdown in some widely used partial or bauhaus primitive, even though it might be a quick render time overall - it might be adding up across an entire experience
If you see a component that has a large gap in the graph compared to it’s children, you can look into that one for refactoring, example

Look at why it rendered, inspect hooks over on the Components tab and drill down
Improving Rendering¶
Components consuming
useStoresshould be wrapped withobserverfrommobx-react-liteNetwork latency - rendering may look janky but if we’re firing off something that doesn’t come back for 3 seconds, that might be why and not necessarily your components rendering
Can we be better with cache?
Lists
FlatList vs FlashList (but also Android vs iOS), there’s a “feel” to it, not always numbers
Optimizing FlatList docs: https://reactnative.dev/docs/optimizing-flatlist-configuration
Writing performant components FlashList docs: https://shopify.github.io/flash-list/docs/fundamentals/performant-components
Keep
renderItemto just worry about presenting the dataDo the work ahead of time: https://reactnative.dev/docs/optimizing-flatlist-configuration#use-basic-components
Blank spaces means the virtualized list cannot keep up with rendering your items fast enough
Reduce unnecessary work
Are you battling TypeScript? Cast if needed
Filter before mapping, not after like this:
const lyricArray: Array<string> = (lyricsMetadata.lines ?? [])
.map(*lyricLine* => lyricLine?.text ?? '')
.filter(*text* => text !== '')
