Tutorial: Building ExpenseApp with React Native and Expo Chapter 1: Web, HTML, CSS & JavaScript Fundamentals Chapter 2: Orientation & Environment Setup Chapter 3: JSX & Core Components Chapter 4: State, Props & Component Architecture Chapter 5: Lists & Layout with Flexbox Chapter 6: Inputs & Form Handling Chapter 7: React Native Tutorial – StickerSmash with Expo Chapter 8: Advanced JavaScript for React Native Chapter 9: Form Handling & Validation with Formik and Yup Chapter 10: Navigation with Expo Router Chapter 11: Navigation Params & Modals Chapter 12: React Hooks, Side Effects & Data Flow Chapter 13: Global State Management with Context API & AsyncStorage Chapter 14: API Integration, Async Operations & Error Handling Chapter 15: Dynamic Bottom Tabs & Drawer Navigation Chapter 16: Advanced JavaScript – Async Patterns Chapter 17: Device APIs – Camera, Image Picker & Location Chapter 18: Notifications & Permissions Chapter 19: Animations & Microinteractions Chapter 20: Performance Optimization Chapter 21: TypeScript Fundamentals for React Native Chapter 22: Theme Context & Dark Mode Chapter 23: Advanced TypeScript – Navigation Types & API Typings Chapter 24: Expo Router Authentication & Transaction Module Chapter 25: Testing Fundamentals (Jest & React Native Testing Library) Chapter 26: Debugging & Troubleshooting Chapter 27: Code Quality & Refactoring Chapter 28: Build & Deployment with Expo (EAS) Chapter 29: Capstone Build-out – Features, Polish & Production Readiness Chapter 30: Capstone Demo, Final Review & Next Steps

Chapter 20: Performance Optimization


In this chapter, we focus on improving the performance, responsiveness, and scalability of our React Native application.

As ExpenseApp grows (more users, more transactions), inefficient rendering and poor list handling can lead to:

  • Slow scrolling
  • UI lag
  • Battery drain
  • Poor user experience

This chapter teaches how to optimize rendering, lists, and component behavior using real-world patterns.


🎯 What You Will Learn

By the end of this chapter, you will:

  • Optimize large lists using FlatList properties
  • Prevent unnecessary re-renders
  • Use React.memo for component optimization
  • Use useMemo and useCallback correctly
  • Apply optimization techniques in ExpenseApp

⚡ Why Performance Optimization Matters


🔹 Real Problem in ExpenseApp

Imagine:

  • 5,000+ expense records
  • Each render recalculates totals
  • Each item re-renders unnecessarily

👉 Result:

  • Laggy scrolling
  • Poor UX

🔹 Goal

👉 Render only what is needed 👉 Avoid repeated calculations 👉 Keep UI smooth and responsive


📜 FlatList Optimization (Core Area)

FlatList is optimized, but requires correct configuration for best performance.


🔹 keyExtractor (MANDATORY)

keyExtractor={(item) => item.id.toString()}

Why Important?

  • Helps React identify items uniquely
  • Prevents unnecessary re-renders
  • Improves diffing performance

👉 In ExpenseApp: Each expense must have a stable unique ID


🔹 initialNumToRender

initialNumToRender={10}

Explanation

  • Number of items rendered initially
  • Smaller value → faster screen load
  • Larger value → smoother initial scroll

👉 ExpenseApp Tip:

  • Use 8–12 for typical lists

🔹 getItemLayout (Huge Performance Boost)

getItemLayout={(data, index) => ({
  length: 70,
  offset: 70 * index,
  index,
})}

Why Important?

  • Skips layout measurement
  • Improves scroll performance
  • Required for large datasets

👉 Use only when:

  • Items have fixed height

🔹 removeClippedSubviews

removeClippedSubviews={true}

Explanation

  • Removes off-screen items from memory
  • Reduces memory usage

👉 Important for:

  • Long expense lists

🔹 windowSize

windowSize={5}

Explanation

  • Controls how many items are rendered around viewport

👉 Smaller value:

  • Less memory 👉 Larger value:
  • Smoother scrolling

🧪 ExpenseApp Optimized List

<FlatList
    data={expenses}
    keyExtractor={(item) => item.id.toString()}
    renderItem={renderItem}
    initialNumToRender={10}
    getItemLayout={(data, index) => ({
        length: 70,
        offset: 70 * index,
        index,
    })}
    removeClippedSubviews
/>

🔁 Avoiding Unnecessary Re-renders


🔹 What Causes Re-renders?

  • State changes
  • Parent re-render
  • New function/object references

👉 Even if UI doesn’t change → React re-renders


🔹 ExpenseApp Problem Example

<FlatList renderItem={({ item }) => <ExpenseItem {...item} />} />

👉 Problem:

  • Function recreated every render
  • All items re-render

🧩 React.memo


🔹 What is React.memo?

Prevents re-render if props are unchanged.


Example

const ExpenseItem = React.memo(({ title, amount }) => {
    console.log("Rendering:", title);

    return (
        <Text>
            {title}: ₹{amount}
        </Text>
    );
});

Why Important?

👉 In ExpenseApp:

  • Only changed items re-render
  • Others remain untouched

🔹 When NOT to Use

  • Very small components
  • Frequently changing props

🧠 useMemo


🔹 What is useMemo?

Caches computed values to avoid recalculating.


🔹 ExpenseApp Problem

const total = expenses.reduce((sum, item) => sum + item.amount, 0);

👉 Runs on every render


🔹 Optimized Version

const total = useMemo(() => {
    return expenses.reduce((sum, item) => sum + item.amount, 0);
}, [expenses]);

Why Important?

👉 Recalculates only when expenses change


🔹 Real Use Cases

  • Total calculation
  • Filtering expenses
  • Sorting data

🔄 useCallback


🔹 What is useCallback?

Caches functions to avoid re-creation.


🔹 ExpenseApp Problem

const renderItem = ({ item }) => <ExpenseItem {...item} />;

👉 New function created every render


🔹 Optimized Version

const renderItem = useCallback(({ item }) => <ExpenseItem {...item} />, []);

Why Important?

  • Keeps function reference stable
  • Works with React.memo

🧪 Combined Optimization Example

const renderItem = useCallback(({ item }) => <ExpenseItem {...item} />, []);

const total = useMemo(() => {
    return expenses.reduce((sum, item) => sum + item.amount, 0);
}, [expenses]);

<FlatList
    data={expenses}
    keyExtractor={(item) => item.id.toString()}
    renderItem={renderItem}
/>;

🚫 Avoid Inline Functions


❌ Bad Practice

<FlatList renderItem={({ item }) => <ExpenseItem {...item} />} />

✅ Good Practice

const renderItem = ({ item }) => <ExpenseItem {...item} />;

👉 Avoid creating new functions inside render


⚡ Additional Optimization Strategies


🔹 Component Splitting

👉 Break large components into smaller ones

Example:

  • ExpenseList
  • ExpenseItem
  • ExpenseHeader

🔹 Image Optimization

  • Use compressed images
  • Avoid large file sizes
  • Lazy load images

🔹 Avoid Heavy State

  • Keep state minimal
  • Avoid storing unnecessary data

🔹 Batch Updates

👉 Combine state updates when possible


📊 Real ExpenseApp Optimization Scenario


Problem

  • Adding one expense causes full list re-render

Solution

  • Use React.memo for ExpenseItem
  • Use useCallback for renderItem
  • Use keyExtractor properly

Result

👉 Only one item re-renders instead of entire list


🎯 When to Optimize


Optimize When:

  • Large datasets
  • Performance issues visible
  • Frequent UI updates

Avoid Premature Optimization

👉 First make it work, then optimize


⚠️ Common Mistakes

  • Overusing useMemo/useCallback
  • Missing dependencies
  • Using React.memo incorrectly
  • Ignoring FlatList props
  • Optimizing without measuring

✅ Best Practices

  • Optimize lists first (biggest impact)
  • Use memoization wisely
  • Keep components simple
  • Measure before optimizing
  • Maintain readability

📘 Chapter Summary

In this chapter, you:

  • Optimized FlatList using advanced props
  • Prevented unnecessary re-renders
  • Used React.memo effectively
  • Applied useMemo and useCallback
  • Improved ExpenseApp performance significantly
Need help with your project?
I can help you explore our services or start an inquiry.