Skip to main content
React Native Introduction
CHAPTER 27 Beginner

Performance and Optimization

Updated: May 16, 2026
7 min read

# CHAPTER 27

Performance and Optimization

1. Introduction

React Native apps run on phones, which have significantly less processing power and RAM than desktop computers. If you write careless JavaScript, your app will drain the user's battery, drop frame rates during animations, and eventually crash. In React, the biggest performance killer is unnecessary re-renders—forcing the phone to redraw a component that hasn't actually changed. In this chapter, we will master Performance and Optimization. We will learn the advanced React triad: React.memo, useMemo, and useCallback, caching our UI and calculations to achieve a flawless 60 Frames Per Second (FPS).

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Identify the cascading re-render problem in React.
  • Use React.memo to cache pure UI components.
  • Use the useMemo hook to cache heavy mathematical calculations.
  • Use the useCallback hook to stabilize function references across renders.
  • Apply aggressive optimization strategies to FlatList.

3. The Re-Render Problem

When a Parent component's state changes, React automatically re-renders the Parent AND every single Child component inside it. Imagine an App with a simple Counter, and a Child component displaying a static heavy image.
javascript
123456789101112
// Every time you click "Increase", the App redraws.
// Because App redraws, <HeavyStaticImage /> is forcibly redrawn too, even though it hasn't changed!
export default function App() {
  const [count, setCount] = useState(0);
  return (
    <View>
      <Button title="Increase" onPress={() => setCount(count + 1)} />
      <Text>{count}</Text>
      <HeavyStaticImage /> 
    </View>
  );
}

4. React.memo (Caching the UI)

We can tell React to skip redrawing the child component by wrapping it in React.memo. memo says: *"Only redraw this component if its PROPS change. If the props are identical to the last render, use the cached visual image."*
javascript
1234567891011121314
import React, { memo } from &#039;react&#039;;
import { View, Text } from &#039;react-native&#039;;

// Wrap the component function in memo()!
const HeavyStaticImage = memo((props) => {
  console.log("I am drawing..."); // This will now only print once!
  return (
    <View style={{ height: 500, width: 500, backgroundColor: &#039;grey&#039; }}>
      <Text>Massive Image Here</Text>
    </View>
  );
});

export default HeavyStaticImage;

5. useMemo (Caching Calculations)

If your component performs a heavy math calculation (like sorting an array of 10,000 products), it will perform that calculation *every single time the component re-renders*, even if the user is just typing in a search box. We use useMemo to cache the *result* of the calculation!
javascript
123456789101112131415161718
import React, { useState, useMemo } from &#039;react&#039;;

export default function ProductList({ rawData }) {
  const [search, setSearch] = useState(&#039;&#039;);

  // 1. The heavy function
  const sortMassiveArray = (data) => {
    console.log("Sorting 10,000 items...");
    return data.sort(); // Takes 2 seconds!
  };

  // 2. The Cache (useMemo)
  // It will ONLY re-run the sort function if 'rawData' actually changes!
  // If the user is just typing in the 'search' box, it skips the math and returns the cached array!
  const sortedData = useMemo(() => sortMassiveArray(rawData), [rawData]);

  return <View>...</View>;
}

6. useCallback (Caching Functions)

In JavaScript, const a = () => {} and const b = () => {} are NOT the same function in memory. Every time a React component re-renders, it recreates all of its internal functions from scratch. If you pass a recreated function down to a child component as a prop, the child says, *"Oh, this function prop is brand new! I must re-render!"* — completely destroying the React.memo optimization we did in Step 4.

We use useCallback to cache the *definition* of the function itself!

javascript
12345678910111213141516171819202122
import React, { useState, useCallback } from &#039;react&#039;;
import ChildComponent from &#039;./ChildComponent&#039;; // Assume this is wrapped in React.memo

export default function App() {
  const [count, setCount] = useState(0);

  // Without useCallback, this function is destroyed and recreated on every render.
  // With useCallback, the memory address stays exactly the same!
  const handlePress = useCallback(() => {
    console.log("Button pressed!");
  }, []); // Empty array means never recreate this function

  return (
    <View>
      <Text>{count}</Text>
      <Button title="Add" onPress={() => setCount(count + 1)} />
      
      {/* Because handlePress has a stable memory address, ChildComponent's React.memo works! */}
      <ChildComponent onCustomPress={handlePress} />
    </View>
  );
}

7. FlatList Optimization

The FlatList is the most performance-sensitive component in React Native. If it lags, the app feels broken.
  1. 1. Always use keyExtractor: Prevents the list from rebuilding identical items.
  1. 2. Optimize renderItem: The function passed to renderItem MUST be wrapped in a useCallback so it isn't recreated 100 times.
  1. 3. Memoize List Items: The individual <ProductCard> you return inside renderItem MUST be wrapped in React.memo.
javascript
123
const renderItem = useCallback(({ item }) => {
  return <MemoizedProductCard data={item} />;
}, []); // Cached renderer!

8. Visual Learning: The Memoization Triad

txt
12345678910
Is the App lagging?

1. Is a UI Component redrawing unnecessarily?
   -> Use `React.memo(Component)`
   
2. Is a massive Math Calculation running unnecessarily?
   -> Use `useMemo(() => math(), [dependencies])`
   
3. Is a Function Prop causing a Memoized Child to redraw?
   -> Use `useCallback(() => function(), [dependencies])`

9. Common Mistakes

  • Memoizing Everything: A massive beginner mistake is wrapping literally every single variable and component in useMemo and memo. Memoization requires RAM to store the cache. If you cache thousands of tiny, fast components, the RAM usage will skyrocket, and checking the cache will actually take longer than just redrawing the UI. ONLY memoize highly complex UI trees or heavy array operations.

10. Best Practices

  • Console.log Auditing: The easiest way to find performance leaks is to put a console.log("Drawing Component X") at the top of your component. If you click a button and the terminal spits out "Drawing Component X" 50 times, you have a massive re-render leak. Fix it with the triad above!

11. Practice Exercises

  1. 1. What higher-order React function is used to wrap an entire UI component so that it only re-renders if its explicit props change?
  1. 2. If you are passing an onPress arrow function down into a heavily optimized <FlatList> child component, what hook must you wrap the arrow function in to preserve its memory address?

12. MCQs with Answers

Question 1

A component contains a useState hook managing a text input, and a heavy function that calculates prime numbers. The prime number calculation takes 3 seconds and freezes the UI every time the user types a single letter. Which hook should be used to cache the prime number result so it isn't recalculated on every keystroke?

Question 2

Why does passing an inline arrow function (e.g., onPress={() => doSomething()}) as a prop to a child component explicitly break the React.memo optimization on that child?

13. Interview Questions

  • Q: Explain the mechanical difference between useMemo and useCallback. What exactly is being cached in each scenario?
  • Q: Detail the cascading re-render behavior in React. How does React.memo intercept this behavior, and what is the computational cost of using React.memo everywhere?
  • Q: A developer has implemented a <FlatList> rendering 5,000 items. Scrolling is incredibly jittery. Detail three specific optimizations you would implement regarding renderItem, list keys, and component memoization to achieve 60 FPS.

14. FAQs

Q: My app is slow in the Expo Go development environment. Does this mean it will be slow in production? A: No! The development environment runs a massive amount of debug code (Hot Reloading, Console logging, Error tracking) that slows the engine down significantly. Always test performance on a fully compiled Production build before panicking!

15. Summary

In Chapter 27, we transitioned from writing functional code to writing enterprise-grade, highly optimized code. We identified the cascading re-render pipeline and surgically intercepted it using the React memoization triad. We utilized React.memo to cache heavy UI architectures, deployed useMemo to store the results of computationally expensive array mathematics, and applied useCallback to stabilize function references across render cycles. You now possess the skills to maintain a flawless 60 FPS under heavy data loads.

16. Next Chapter Recommendation

Our application is lightning-fast and perfectly responsive. Now, let's give the user the ability to customize its appearance. Proceed to Chapter 28: Theming and Dark Mode.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·