React Native · Mobile UI at native speed

How do you find and fix memory leaks?

MediummemoryleakscleanupUpdated Oct 2026
Quiz this track

Short answer

Look for listeners, timers, subscriptions and async callbacks that outlive a screen, clean them up in effects, and confirm with native memory tools rather than guessing from a rising graph.

A React Native leak is usually a retained reference: a global event subscription that still points at a component, a timer that never clears, or a promise that resolves after unmount and calls setState. The JS heap grows, or native views stay alive after navigation.

tsx
import { useEffect, useState } from "react";
import { Keyboard } from "react-native";

export function useKeyboardHeight() {
  const [height, setHeight] = useState(0);

  useEffect(() => {
    const show = Keyboard.addListener("keyboardDidShow", (event) => {
      setHeight(event.endCoordinates.height);
    });
    const hide = Keyboard.addListener("keyboardDidHide", () => setHeight(0));

    return () => {
      show.remove();
      hide.remove();
    };
  }, []);

  return height;
}
Every addListener needs a matching remove in the effect cleanup.

Common leak sources

  • AppState, Keyboard, NetInfo and navigation listeners without cleanup
  • setInterval or setTimeout that is never cleared
  • Async requests that update state after unmount, unless aborted
  • Global stores or event emitters retaining screen callbacks
  • Large images or base64 strings kept in state or caches
  • WebViews and native views that are not torn down properly

AbortController is the clean fix for in-flight requests. Pass its signal to fetch and abort in the effect cleanup. For subscriptions, return the library's remove function rather than a custom flag that only suppresses the warning.

A growing memory graph is not proof of a leak. Caches, image decode buffers and normal GC behaviour can look similar. Take heap snapshots before and after a repeated flow and compare retained objects.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1Why does an uncleared interval leak memory?
  2. 2How do you cancel a fetch when a screen unmounts?
  3. 3How do you confirm a leak with a heap snapshot?
  4. 4Why is a global event emitter a common leak source?

Say it in the interview

I look for references that outlive a screen: listeners, timers, subscriptions and async callbacks. Each effect that subscribes returns a cleanup, and requests get an AbortController so they cannot update state after unmount. To confirm, I take heap snapshots around a repeated navigation flow and compare retained objects rather than trusting a rising memory graph.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live React Native mock interview and get scored feedback on depth, clarity and confidence.