# The Complete Guide to React Native Debugging in 2026

If you last debugged a React Native app in 2023, almost every tool you reached for is gone. Flipper is deprecated. The standalone React Native Debugger has stopped receiving Hermes updates. The old "Debug JS Remotely" toggle no longer exists in modern React Native. And as of React Conf 2025, the New Architecture (Fabric renderer + TurboModules) is no longer an opt-in — it is the only architecture, which means the debugging entry points, the crash signatures, and the profiling flows are all different.

This guide is a complete, up-to-date walkthrough of React Native debugging in 2026 — what tool to use for which problem, how to attach it, what to do when your screen goes blank or your app crashes only in release mode, and how to keep production instrumented so you find bugs before your users do.

![Developer debugging a mobile app on a laptop next to a phone showing React Native code](https://images.unsplash.com/photo-1517694712202-14dd9538aa97?w=1200)
*The 2026 React Native debugging stack is Hermes-first, DevTools-native, and increasingly Chrome DevTools Protocol-based. Photo by Emile Perron on Unsplash.*

## What React Native debugging looks like in 2026

React Native debugging is the process of inspecting JavaScript runtime state, native module behavior, network traffic, and performance metrics in a React Native or Expo application to identify and fix defects. In 2026, the default debugger is React Native DevTools, which ships built-in with React Native 0.76+ and attaches directly to the Hermes runtime through the Chrome DevTools Protocol. You launch it by pressing `j` in the Metro terminal.

That short definition hides three shifts worth spelling out, because they change how you approach every bug:

1. **Hermes is the default engine.** JavaScriptCore is on its way out. All the modern debugging entry points — CPU profiles, heap snapshots, breakpoints — assume Hermes and talk to it directly through CDP.
2. **The New Architecture is mandatory.** Fabric renders your UI, TurboModules replace the old async bridge, and Codegen produces the C++ interfaces both sides speak. A whole class of "message dropped on the bridge" bugs is gone; a new class of Codegen mismatches and synchronous C++ crashes is here.
3. **Debugging is browser-aligned.** The React Native DevTools frontend is a customized build of Chrome DevTools. If you know how to debug a web app in Chrome, most of what you know now works on device.

The rest of this guide is organized around that reality: the tool you already have, when to reach for something else, and the workflows that actually catch bugs in 2026.

## The 2026 React Native debugging tool stack

Here is the shortest possible mapping between "what am I trying to do" and "what do I open":

| I want to…                                                                          | Reach for                                       |
| ----------------------------------------------------------------------------------- | ----------------------------------------------- |
| Set a breakpoint, inspect variables, step through JS                                | **React Native DevTools** (press `j` in Metro)  |
| Watch network requests                                                              | **DevTools → Network** (or Reactotron)          |
| Inspect the component tree, props, state, hooks                                     | **DevTools → Components** (React DevTools)      |
| Measure render performance                                                          | **DevTools → Profiler** or the Hermes CPU profile |
| Trace Redux, Zustand, or MMKV state                                                 | **Reactotron**                                  |
| Debug a native crash on iOS                                                         | **Xcode** — Debug Navigator + `.crash`/`.ips` symbolication |
| Debug a native crash on Android                                                     | **Android Studio Logcat** + `ndk-stack`         |
| Find why a production build is crashing users you can't reach                       | **Sentry, Bugsnag, or Firebase Crashlytics** with uploaded source maps |
| Reproduce a "works on my machine" release-only bug                                  | An EAS internal-distribution build + Sentry     |
| Live-tweak UI without a full reload                                                 | **Fast Refresh** (on by default; press `r` to force reload) |

Everything else is an instance of one of these. Keep the table close for the first month; you'll internalize it fast.

## Setting up React Native DevTools

If you are on React Native 0.76 or later (or Expo SDK 52+), you already have DevTools installed. There is nothing to `npm install`. The workflow is:

1. Start your app with `npx expo start` or `npx react-native start`.
2. In the Metro terminal, press `j`.
3. A Chromium window opens with Sources, Console, Network, Performance, Memory, and Components tabs — attached to your Hermes runtime on the connected device or simulator.

The important thing about this architecture is that DevTools connects to the Hermes CDP endpoint in your app process. Your JavaScript keeps running inside Hermes on the device. It is not being shipped over the network to Chrome to be executed there, the way "Debug JS Remotely" used to work. That old model produced a legendary category of Heisenbugs where a bug would disappear the moment the debugger attached, because your code was suddenly running on V8 in Chrome instead of Hermes on the device. That entire class of bug is gone in 2026.

Two practical consequences:

- **Timing-sensitive bugs are now reproducible under the debugger.** Native modules, animations, `InteractionManager` callbacks all run at real device speed.
- **`console.log` output is fast.** Logs stream over CDP; you can leave them on during profiling without dropping frames the way the old socket-based bridge did.

![Chrome DevTools open on a laptop screen, inspecting a React application](https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=1200)
*React Native DevTools is a customized build of Chrome DevTools, so most muscle memory from web debugging transfers directly. Photo by Ilya Pavlov on Unsplash.*

## Debugging JavaScript and React components

Ninety percent of React Native bugs live in JavaScript, which is why DevTools is the default answer. The three views you will use daily:

**Sources.** Set breakpoints by clicking a line number. When execution pauses, the call stack, scope, watches, and closures panel all work exactly like the browser. You can also drop `debugger;` into your code — the DevTools window will pop to front on hit. For code that only runs on startup, set the breakpoint, then trigger a reload with `r` in Metro or shake → Reload.

**Console.** `console.log`, `console.warn`, `console.error`, and `console.table` all render. `console.trace` gives you a stack. If you are debugging a hook that runs on every render, prefer `console.count('MyComponent render')` so you can see cadence at a glance.

**Components (React DevTools).** This is the React inspector, embedded in the same window. Select any element to see its props, state, hooks, and re-render reasons. Turn on "Highlight updates when components render" during a suspicious interaction — anything blinking that shouldn't be re-rendering is a wasted render, and usually a missing `React.memo` or a new object literal being passed as a prop.

For the New Architecture specifically, one Components-panel behavior is worth flagging: Fabric elements now render synchronously in the same commit as your React tree. If a prop change reaches your component tree but not the native view, the mismatch is almost always in the Codegen spec — either a stale generated file or a props type mismatch that Codegen accepted. Regenerate before you debug further.

## Debugging network requests

Open the Network tab in DevTools. Every `fetch`, `XMLHttpRequest`, and Axios call is captured, including headers, request body, response body, timings, and status. This replaces the Flipper Network plugin entirely.

Two gotchas that still catch people:

- **WebSocket frames are not captured** in the Network panel. Use `console.log` on your WebSocket handler, or watch traffic at the OS level with Charles Proxy / Proxyman.
- **Requests made from a native module** (e.g., a native SDK's HTTP client) do not appear in the JS Network panel. Use Charles Proxy or platform tooling.

For iOS simulator SSL inspection, install the Charles root certificate in the simulator's Trust Store — this is easier than it used to be, but it is still a one-time setup you will forget you did.

## Debugging state (Redux, Zustand, MMKV, TanStack Query)

DevTools does not natively understand your state library. The tool that does is **Reactotron**, which is still actively maintained and now has first-class Hermes and New Architecture support.

Install it as a dev-only dependency and initialize it in a file you only import in development. Reactotron gives you:

- A Redux state tree with time-travel (via a middleware or the `redux-devtools-extension` bridge).
- A live view of Zustand stores.
- MMKV read/write logs, which are invaluable because MMKV is synchronous and easy to accidentally block the UI thread with.
- TanStack Query devtools output — the queries, their cache keys, staleness, and refetch reasons.
- A custom command panel so you can inject "log in as user X" or "clear cache" buttons for QA.

Wire Reactotron up once per project. The five minutes it costs you saves hours the first time a Redux action fires with a payload nobody wrote.

## Debugging the New Architecture

Fabric and TurboModules eliminated the old async message bridge, which fixed a lot and broke a little. The bugs you now see:

- **Codegen mismatches.** Your TypeScript spec says a prop is `string`; the native side reads it as `number`. In the old world, this would silently no-op. In the new world it produces a hard C++ crash on first render. Fix: regenerate with `npx react-native codegen` (or clean-build Expo), and always keep your `.ts` spec, `.podspec`, and `build.gradle` in sync.
- **Synchronous TurboModule crashes.** The bridge used to swallow exceptions from native modules. TurboModules can be called synchronously, so a thrown exception unwinds straight to your JavaScript and crashes the app if you don't `try/catch`. Wrap every TurboModule call site that touches user input.
- **View flattening surprises.** Fabric flattens Views aggressively for performance. A `View` with no styles that used to be measurable via `onLayout` may no longer exist as a native view at all. If a layout callback stops firing after upgrading, add a `collapsable={false}` and re-test.

For deeper native inspection, launch the app from Xcode or Android Studio and use their debuggers — LLDB on iOS, LLDB or Java Debugger on Android — with the app running. This is not different from before, but it is the only path when the crash is below the JS layer.

## Performance profiling with the Hermes sampling profiler

If your app feels slow but you don't have a specific crash, the fastest way to find the cause is a Hermes CPU profile.

1. In your app, wrap the interaction you want to measure with `HermesInternal.enableSamplingProfiler()` / `disableSamplingProfiler()` — or trigger it from the DevTools Performance tab's "Record" button, which now maps to the same primitive.
2. Perform the interaction (open the slow screen, tap the sluggish button).
3. Stop recording. DevTools will render a flame chart of JavaScript execution, with millisecond-level resolution.

What to look for:

- **A single tall function** dominating the flame chart is usually an expensive `.map` over a large array, or JSON parsing on the JS thread.
- **A wide, shallow bar of `render` calls** is a re-render storm — every child rendering because a parent's memoized prop lost referential equality.
- **Long gaps between JS frames** with nothing in them are native-side work — probably an image decode, a layout pass, or a synchronous bridge call on the old architecture. Cross-check with the Systrace overlay if you need to see the native side too.

For heavy investigations, drop the profile file into Chrome DevTools' Performance tab on your desktop for a bigger view than the embedded panel.

![Screens showing performance graphs and CPU flame charts](https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=1200)
*A Hermes CPU profile visualized as a flame chart makes it obvious where JavaScript is spending time. Photo by Luke Chesser on Unsplash.*

## Debugging native crashes

If your JavaScript throws, you see a red screen in development or a JS error in production. If your native code throws, the app dies immediately with no red screen. That is the tell.

**iOS.** Attach with Xcode → Product → Attach to Process → your app. When it crashes, the Debug Navigator shows the thread that died and the stack. For production crashes, download the `.ips` file from App Store Connect, symbolicate it with `atos` and the matching `.dSYM`, and the stack becomes readable — this is the same flow Sentry and Crashlytics automate for you if you upload dSYMs during your EAS build.

**Android.** `adb logcat` is still the answer. Filter with `ReactNativeJS` for JS logs, or `System.err` and `AndroidRuntime` for native. A JNI crash shows a memory address; run it through `ndk-stack` with the matching `libhermes.so` symbols and you get a real stack. Crashlytics does this for production.

**Hermes JS crashes** are different from either. They emit a stack trace with obfuscated file paths (e.g., `index.android.bundle:1:1234`). Upload your Hermes source map to Sentry or Bugsnag as part of your CI build, and those stacks become source-mapped back to your original TypeScript.

## Production monitoring

Development debugging tells you about bugs you can reproduce. Production monitoring tells you about the ones you can't. In 2026 the mature choices are Sentry, Bugsnag, and Firebase Crashlytics. All three now support:

- Hermes source map upload during EAS build via a plugin.
- Native crash symbolication (dSYM on iOS, ProGuard/R8 mappings on Android, Hermes bundles).
- Release health metrics — crash-free sessions, adoption rate, regression comparison across versions.
- Breadcrumbs (recent navigation events, network requests, console logs) attached to each crash.

Set up one of them on day one of your project. Retroactively wiring it up after your first App Store crash spike is much harder than pre-installing it and never seeing the alert.

## Common debugging workflows

A few debugging scenarios come up often enough that they deserve a named workflow.

**Blank screen on device, everything works in the emulator.** Almost always a Metro bundler mismatch — your device is holding the old bundle after a `package.json` change forced a Metro restart. Fix: shake the device → Reload, or close and reopen the app. This is the same class of bug that hits the RapidNative preview pipeline, where a template dependency change severs the running Expo Go session; the app is fine, the client just needs a reload. If you are running a cloud preview and it looks blank, check the workload logs for a fresh `bundled in …ms` — if you see it, the bundle is fine and only the phone needs the reload.

**Red screen with an unhelpful stack.** Turn on source maps in dev if you haven't (they are on by default in modern React Native but people disable them for build speed). If the stack points at a minified file, your source maps are not being generated.

**Fast Refresh not refreshing.** Usually one of your files has a syntax error that Fast Refresh could not compile, and it silently fell back to full-reload mode. Save the file with a working state; refresh resumes.

**Repeated mid-stream reloads during development.** In our own tooling for the RapidNative editor we learned the hard way that reloading while an app is streaming its content restarts the whole app and discards any partial render — reloads must be gated on real dependency changes, not on every file update. If you write custom tooling around HMR, check whether you're triggering more reloads than you think.

**"Works locally, crashes in release."** The two most common causes are (1) a `console.log` that only ran because the debugger was attached and papered over a race, and (2) a native module bundled differently in release. Build a local release build (`npx expo run:ios --configuration Release` or the Android equivalent), reproduce, and attach Xcode/Android Studio to it.

## How AI-generated apps sidestep entire bug classes

At [RapidNative](https://www.rapidnative.com/?utm_source=blog&utm_medium=content&utm_campaign=react-native-debugging-guide-2026) we build a lot of React Native and Expo apps from natural-language prompts, which gives us a data set most teams don't have: what bugs the codebase-level defaults actually prevent. Two patterns are worth borrowing regardless of whether you use an AI builder:

- **Every generated screen ships with the modern data-fetching stack pre-wired** — TanStack Query for server state, Zustand or Redux Toolkit for client state, and a Supabase client for the database — with the debugger hooks already attached. You do not have to remember to install Reactotron. The most productive debugging setup is the one that came pre-installed.
- **Migrations, RLS policies, and generated database types stay in lockstep.** When schema and types drift, you get exactly the class of runtime bug that produces a blank screen with no error in the console. Regenerating types on every schema change eliminates it. You can [describe the app you want to build](https://www.rapidnative.com/?utm_source=blog&utm_medium=content&utm_campaign=react-native-debugging-guide-2026) and see the whole stack come up debugged from the first render.

If you want a broader look at how AI-generated codebases hold up under debugging pressure, we wrote about [how we test AI-generated React Native code at scale](https://www.rapidnative.com/blogs/how-we-test-ai-generated-react-native-code-at-scale?utm_source=blog&utm_medium=content&utm_campaign=react-native-debugging-guide-2026) and about [keeping AI-generated apps fast](https://www.rapidnative.com/blogs/how-ai-generated-apps-stay-fast-our-performance-approach?utm_source=blog&utm_medium=content&utm_campaign=react-native-debugging-guide-2026).

## Frequently asked questions

**Is React Native Debugger still usable in 2026?**
No. Standalone React Native Debugger stopped receiving Hermes updates in 2023 and is not compatible with the New Architecture. Use React Native DevTools (press `j` in Metro) instead. It ships built-in with React Native 0.76+ and Expo SDK 52+ and covers every use case the standalone debugger did.

**Do I still need Flipper?**
No. Flipper was deprecated as a first-class React Native tool in 2023 and its plugins have moved elsewhere. Network requests, React inspection, and performance profiling all live in React Native DevTools. Redux/Zustand/MMKV inspection moved to Reactotron.

**How do I debug a release build?**
Build a release binary locally, attach Xcode or Android Studio to the running process, and use the platform's native debugger for crashes below the JS layer. For JS-only issues in release, upload Hermes source maps to Sentry or Bugsnag during your EAS build so production stacks resolve back to your TypeScript.

**Can I still use `console.log` for debugging?**
Yes. In 2026 it is fast (streamed over CDP), does not drop frames, and integrates with the DevTools Console. Prefer `console.warn`/`console.error` for signals you want to notice in a busy log, and `console.count` for hooks that fire too often.

**What is the fastest way to find a slow render?**
Open React DevTools → Components, enable "Highlight updates when components render," and interact with the screen. Anything that lights up on an interaction it shouldn't be affected by is a wasted render. Follow up with a Hermes CPU profile if you need microsecond-level cost.

## Wrap-up

React Native debugging in 2026 is genuinely better than it was three years ago — one built-in tool covers most cases, Hermes runs debug and release with the same semantics, and the New Architecture removed the async bridge that used to swallow half your errors. The catch is that the muscle memory from the Flipper era does not transfer. Start with React Native DevTools, add Reactotron when you need state visibility, wire Sentry in on day one, and you have covered the ninety-percent case before you have written a line of business logic.

If you want to skip the setup entirely and start with a project where the whole debugging stack is already wired up, [describe the app you want and generate it in the RapidNative editor](https://www.rapidnative.com/?utm_source=blog&utm_medium=content&utm_campaign=react-native-debugging-guide-2026) — every project ships with DevTools, source maps, and a testable Supabase backend attached from the first prompt.

Further reading: the official [React Native debugging docs](https://reactnative.dev/docs/debugging), the [Hermes engine documentation](https://hermesengine.dev/), and the [Chrome DevTools Protocol reference](https://chromedevtools.github.io/devtools-protocol/) for anyone building custom debugging tools on top of the same primitives.
