Memoization

Back

Loading concept...

🚀 React Native Memoization: The Speed Superpower

Imagine your phone is a super-smart assistant. But every time you ask it to remember something, it forgets and has to figure it out all over again. Annoying, right? Memoization is like giving your assistant a magical notebook that remembers answers forever!


🎯 What is Memoization?

Think of memoization like a smart chef in a kitchen.

When you order pancakes, the chef doesn’t re-read the recipe every single time. They remember it! They only check the recipe if you ask for something new.

Memoization = Remembering answers so you don’t recalculate them.

graph TD A["User asks for calculation"] --> B{Already calculated?} B -->|Yes| C["Return saved answer ⚡"] B -->|No| D["Calculate answer"] D --> E["Save to memory"] E --> C

In React Native, your app does lots of work. Without memoization, it does the same work over and over. With memoization, it says: “Hey, I already figured this out. Here’s the answer!”


📦 useMemo Hook

The “Remember My Answer” Hook

Imagine you have a toy box with 1000 toys. Every time someone asks “how many red toys?”, you count them all again. That’s exhausting!

useMemo is like writing the answer on a sticky note. Next time someone asks, you just read the note!

When to Use It

Use useMemo when you have:

  • Heavy calculations
  • Filtering large lists
  • Complex data transformations

Simple Example

import { useMemo, useState } from 'react';

function ToyCounter({ toys }) {
  const [filter, setFilter] = useState('red');

  // Without useMemo: Counts EVERY render 😰
  // With useMemo: Counts only when toys change! 🎉

  const redToyCount = useMemo(() => {
    console.log('Counting toys...');
    return toys.filter(t => t.color === 'red').length;
  }, [toys]); // Only recalculate if toys changes

  return <Text>Red toys: {redToyCount}</Text>;
}

The Magic Formula

const result = useMemo(() => {
  // Your expensive calculation here
  return someValue;
}, [dependency1, dependency2]);
Part What It Does
() => {} The calculation to remember
[deps] When to recalculate
result The remembered answer

⚠️ Don’t Overuse It!

Not everything needs useMemo. Simple math like 2 + 2 doesn’t need remembering. Only use it for heavy work.


🎣 useCallback Hook

The “Remember My Function” Hook

Here’s a fun story: Every time your component re-renders, React creates brand new functions. Even if they do the same thing!

It’s like your mom asking “Who wants ice cream?” and you thinking it’s a different question each time because she wore a different hat.

useCallback keeps the same function around, so other parts of your app recognize it.

Why Does This Matter?

When you pass functions to child components, React checks: “Is this the same function?” If it’s new every time, the child re-renders needlessly!

Example: The Counting Button

import { useCallback, useState } from 'react';

function ParentComponent() {
  const [count, setCount] = useState(0);

  // ❌ Without useCallback: New function every render
  // const handlePress = () => setCount(c => c + 1);

  // ✅ With useCallback: Same function, recognized!
  const handlePress = useCallback(() => {
    setCount(c => c + 1);
  }, []); // Empty array = never changes

  return <MyButton onPress={handlePress} />;
}

useMemo vs useCallback

Feature useMemo useCallback
Returns A value A function
Use for Calculations Event handlers
Example Filtered list onPress, onChange

Pro tip: useCallback(fn, deps) is the same as useMemo(() => fn, deps)


🛡️ React.memo

The “Don’t Re-render Me!” Wrapper

Imagine you have a picture frame. The picture inside never changes. But someone keeps taking it off the wall and putting it back up every second. Wasteful!

React.memo tells React: “Only update this component if its props actually changed.”

Basic Usage

import { memo } from 'react';

// Without memo: Renders every time parent renders
// With memo: Only renders if props change! ✨

const ExpensiveCard = memo(function ExpensiveCard({
  title,
  data
}) {
  console.log('Card rendered!');
  return (
    <View>
      <Text>{title}</Text>
      {/* Complex rendering here */}
    </View>
  );
});

The Power Combo 💪

For maximum speed, combine all three:

const Parent = () => {
  const [items] = useState([...]);

  // 1. useMemo: Remember the filtered list
  const filtered = useMemo(() =>
    items.filter(i => i.active),
  [items]);

  // 2. useCallback: Remember the handler
  const handleSelect = useCallback((id) => {
    console.log('Selected:', id);
  }, []);

  // 3. React.memo: Child only updates when needed
  return <MemoizedList
    data={filtered}
    onSelect={handleSelect}
  />;
};

const MemoizedList = memo(({ data, onSelect }) => {
  return data.map(item => (
    <TouchableOpacity
      key={item.id}
      onPress={() => onSelect(item.id)}
    >
      <Text>{item.name}</Text>
    </TouchableOpacity>
  ));
});

🎯 Memoization Strategies

Strategy 1: The Component Boundary

Break your app into small, memoized pieces:

graph TD A["Parent Component"] --> B["Memo: Header"] A --> C["Memo: List"] A --> D["Memo: Footer"] C --> E["Memo: ListItem 1"] C --> F["Memo: ListItem 2"] C --> G["Memo: ListItem N"]

Strategy 2: Lift Expensive Calculations

Move heavy work to the top, pass results down:

// ✅ Good: Calculate once at top
const ExpensiveParent = ({ rawData }) => {
  const processed = useMemo(() =>
    heavyProcessing(rawData),
  [rawData]);

  return (
    <>
      <ChildA data={processed} />
      <ChildB data={processed} />
      <ChildC data={processed} />
    </>
  );
};

Strategy 3: Stable References

Keep object and array references stable:

// ❌ Bad: New object every render
<MyComponent style={{ flex: 1 }} />

// ✅ Good: Stable reference
const styles = { flex: 1 };
<MyComponent style={styles} />

// Or with useMemo for dynamic values
const style = useMemo(() => ({
  backgroundColor: isActive ? 'blue' : 'gray'
}), [isActive]);

When to Memoize (Decision Tree)

Situation Action
Simple component, few props Skip memo
Component renders often with same props Use memo
Expensive calculation in render Use useMemo
Function passed to memoized child Use useCallback
List with many items Memo each item

📊 Performance Profiling

Finding the Slow Spots

Before you optimize, you need to find the problems! It’s like being a detective looking for clues.

Tool 1: React DevTools Profiler

The Profiler shows you exactly what’s re-rendering and why.

Steps to use:

  1. Install React DevTools
  2. Open Profiler tab
  3. Click “Record”
  4. Use your app
  5. Click “Stop”
  6. See the flame chart!

Tool 2: Console Logging

Simple but effective:

const MyComponent = memo(({ data }) => {
  console.log('🔥 MyComponent rendered!');

  const result = useMemo(() => {
    console.log('📊 Calculating result...');
    return expensiveWork(data);
  }, [data]);

  return <Text>{result}</Text>;
});

Tool 3: Performance.now()

Measure exactly how long things take:

const startTime = performance.now();

// Your expensive operation
const result = heavyCalculation();

const endTime = performance.now();
console.log(`Took ${endTime - startTime}ms`);

Reading Profiler Results

graph TD A["Open Profiler"] --> B["Record"] B --> C["Interact with App"] C --> D["Stop Recording"] D --> E["Check Flame Chart"] E --> F{Long Bars?} F -->|Yes| G["Investigate that component"] F -->|No| H["Performance is good! 🎉"]

What to Look For

Sign Problem Solution
Same component renders many times Missing memo Add React.memo
Expensive calculation each render Missing useMemo Add useMemo
New function causes child re-render Missing useCallback Add useCallback

🧹 Memory Management

The Cleanup Story

Memoization saves things in memory. But what if you save too much? Your app gets heavy and slow, like a backpack full of rocks!

Rule 1: Clean Up Effects

useEffect(() => {
  const subscription = data.subscribe();

  // ✅ Always clean up!
  return () => {
    subscription.unsubscribe();
  };
}, [data]);

Rule 2: Avoid Memory Leaks in Callbacks

const MyComponent = () => {
  const [data, setData] = useState(null);

  // ✅ Check if component is still mounted
  useEffect(() => {
    let isMounted = true;

    fetchData().then(result => {
      if (isMounted) {
        setData(result);
      }
    });

    return () => {
      isMounted = false;
    };
  }, []);

  return <Text>{data}</Text>;
};

Rule 3: Don’t Over-Memoize

Every useMemo and useCallback uses memory!

// ❌ Bad: Unnecessary memoization
const doubled = useMemo(() => count * 2, [count]);

// ✅ Good: Simple math doesn't need memo
const doubled = count * 2;

The Memory Balance

graph LR A["Too Little Memoization"] --> B["Slow renders 🐌"] C["Just Right"] --> D["Fast &amp; lean 🚀"] E["Too Much Memoization"] --> F["Memory bloat 🎈"]

Memory Tips Summary

Do This Avoid This
Memoize expensive calculations Memoizing simple math
Clean up subscriptions Orphaned listeners
Use appropriate dependency arrays Empty arrays when deps exist
Profile before optimizing Blind optimization

🎁 Quick Reference

The Three Musketeers

Tool Purpose Returns
useMemo Remember a value Calculated value
useCallback Remember a function Stable function
React.memo Prevent re-renders Memoized component

When to Use Each

// useMemo: Heavy calculations
const sorted = useMemo(() =>
  items.sort((a, b) => a.name.localeCompare(b.name)),
[items]);

// useCallback: Functions passed to children
const handlePress = useCallback(() => {
  doSomething(id);
}, [id]);

// React.memo: Components that receive stable props
const ListItem = memo(({ item, onPress }) => (
  <TouchableOpacity onPress={onPress}>
    <Text>{item.name}</Text>
  </TouchableOpacity>
));

The Golden Rules

  1. Measure first - Don’t optimize blindly
  2. Start simple - Add memoization only when needed
  3. Check dependencies - Wrong deps = bugs
  4. Clean up - Prevent memory leaks
  5. Profile regularly - Performance changes over time

🌟 You Did It!

You now understand React Native’s memoization superpowers:

  • useMemo - Remember expensive values
  • useCallback - Remember functions
  • React.memo - Prevent unnecessary re-renders
  • Strategies - When and how to apply them
  • Profiling - Find performance issues
  • Memory - Keep your app lean

Your apps will now run smoother, faster, and your users will love it! 🚀

Remember: The best optimization is one you can measure. Profile first, optimize second, and your app will thank you!

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.