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

Perf monitor

npx react-devtools

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* }) => {

flamegraph1

  • 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,
}) {

flamegraph2

  • 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

flamegraph3

  • Look at why it rendered, inspect hooks over on the Components tab and drill down

Improving Rendering

  1. Components consuming useStores should be wrapped with observer from mobx-react-lite

    1. Docs: https://mobx.js.org/react-integration.html#how-can-i-further-optimize-my-react-components

  2. Network 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

    1. Can we be better with cache?

  3. Lists

    1. FlatList vs FlashList (but also Android vs iOS), there’s a “feel” to it, not always numbers

      1. Optimizing FlatList docs: https://reactnative.dev/docs/optimizing-flatlist-configuration

      2. Writing performant components FlashList docs: https://shopify.github.io/flash-list/docs/fundamentals/performant-components

    2. Keep renderItem to just worry about presenting the data

      1. Do the work ahead of time: https://reactnative.dev/docs/optimizing-flatlist-configuration#use-basic-components

      2. Blank spaces means the virtualized list cannot keep up with rendering your items fast enough

  4. Reduce unnecessary work

    1. Are you battling TypeScript? Cast if needed

    2. Filter before mapping, not after like this:

const lyricArray: Array<string> = (lyricsMetadata.lines ?? [])
      .map(*lyricLine* => lyricLine?.text ?? '')
      .filter(*text* => text !== '')