← back to blog
10 min read

Debugging React Native Like a Pro

Advanced debugging techniques for React Native apps, from Flipper to native debugging and performance profiling.

React NativeDebuggingTools

console.log debugging only gets you so far. Here are the tools and techniques I use for serious debugging.

1. Flipper

Flipper is the official debugging tool for React Native. Install it and enable in your app:

// ios/Podfile
use_flipper!()

// android/app/build.gradle debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")

Key Flipper Features:

Network Inspector See every network request, including headers and response bodies. Filter by status code to find failed requests.

React DevTools Inspect component hierarchy, props, and state directly in Flipper.

Layout Inspector Visual debugging for layout issues. Highlights component bounds and shows style properties.

Databases Inspect AsyncStorage, SQLite, and other local databases.

2. React Native Debugger

A standalone app combining React DevTools and Redux DevTools:

brew install react-native-debugger

Enable remote debugging (shake device → Debug) and the debugger auto-connects.

Redux DevTools Features:

  • Time-travel debugging
  • Action replay
  • State diff between actions

3. Native Debugging

Sometimes bugs are in native code. You need Xcode/Android Studio.

iOS (Xcode):

  • Open ios/YourApp.xcworkspace
  • Set breakpoints in native code
  • Run from Xcode (not yarn ios)
  • Use LLDB console for inspection
  • Android (Android Studio):

  • Open android/ folder
  • Attach debugger to running process
  • Set breakpoints in Java/Kotlin code
  • Viewing Native Logs:

    # iOS
    xcrun simctl spawn booted log stream --level debug | grep YourApp
    

    # Android adb logcat *:S ReactNative:V ReactNativeJS:V

    4. Performance Profiling

    JS Performance:

    Enable the Performance Monitor (shake → Perf Monitor) and watch:

    • JS FPS (should be 60)
    • UI FPS (should be 60)
    • RAM usage
    Finding Slow Renders:

    Use React's Profiler:

    import { Profiler } from 'react';
    

    function onRenderCallback( id, phase, actualDuration, baseDuration, startTime, commitTime ) { console.log(${id} rendered in ${actualDuration}ms); }

    <Profiler id="MyComponent" onRender={onRenderCallback}> <MyComponent /> </Profiler>

    Systrace (Android):

    # Start trace
    yarn react-native start --reset-cache
    

    # In another terminal adb shell "echo 0 > /sys/kernel/debug/tracing/tracing_on" adb shell "echo 1 > /sys/kernel/debug/tracing/tracing_on"

    # Reproduce the issue, then: adb shell "echo 0 > /sys/kernel/debug/tracing/tracing_on" adb pull /sys/kernel/debug/tracing/trace ./trace.txt

    5. Crash Debugging

    JavaScript Crashes:

    Use error boundaries:

    class ErrorBoundary extends React.Component {
      state = { hasError: false, error: null };
    

    static getDerivedStateFromError(error) { return { hasError: true, error }; }

    componentDidCatch(error, errorInfo) { // Log to crash reporting service crashlytics().recordError(error); console.log('Error caught:', error, errorInfo); }

    render() { if (this.state.hasError) { return <ErrorFallback error={this.state.error} />; } return this.props.children; } }

    Native Crashes:

    For iOS, check crash logs:

    • Xcode → Window → Devices and Simulators → View Device Logs
    For Android:
    adb logcat -b crash

    Use Sentry or Crashlytics for production crash reporting.

    6. Common Issues & Solutions

    "Red Box" Errors: Read the stack trace carefully. The actual error is usually in the first few lines.

    Infinite Re-renders: Add logging to useEffect:

    useEffect(() => {   console.log('Effect triggered, deps:', dep1, dep2); }, [dep1, dep2]);

    Memory Leaks: Use Flipper's memory graph or React DevTools to find components that don't unmount.

    Network Issues: Check if the device can reach your API. Common issue: localhost doesn't work on physical devices.

    // Use your machine's IP instead
    const API_URL = __DEV__
      ? 'http://192.168.1.100:3000'
      : 'https://api.production.com';

    Debugging is a skill. The more you practice with these tools, the faster you'll find bugs.