Debugging Tools

Every React Native app eventually breaks in a way that isn't obvious from just staring at the code. The good news is React Native has a genuinely solid debugging toolkit — from the humble console.log() all the way up to a full desktop inspector that shows you network requests, component state, and stored data at a glance. This page walks through the tools you'll reach for most often, roughly in the order you'd typically use them.

console.log(): The First Line of Defense

The humble console.log() works in React Native exactly like it does in any other JavaScript environment, which makes it the fastest way to check a value without setting anything up. Where the output shows up depends on how you're running the app: with a standard setup, logs appear directly in the terminal window running the Metro bundler; if you've enabled remote JS debugging (running your JS in a desktop browser tab instead of on-device), the same logs appear in that browser's own developer console instead.

function handleSubmit(formValues) {
  console.log('Submitting form with:', formValues);
  // ... rest of the submit logic
}

It's quick, but it doesn't scale well — sprinkling dozens of console.log() calls through a growing app gets noisy fast, which is where the tools below start to earn their keep.

The In-App Developer Menu

Every React Native app in development includes a built-in Developer Menu, briefly introduced back in Your First App. Open it by shaking a physical device, or with Cmd+D on an iOS simulator / Ctrl+M (or Cmd+M on Mac) on an Android emulator. From there you get a handful of genuinely useful options:

OptionWhat it does
ReloadForce-reloads the JS bundle from scratch, useful when Fast Refresh gets stuck
Debug Remote JSRuns your app's JavaScript in a desktop browser instead of on-device, so you can use browser devtools/breakpoints
Toggle InspectorTurns on the Element Inspector (covered below) for tapping any visible element

React Native DevTools and Flipper

For anything beyond quick log statements, React Native DevTools (and its predecessor, Flipper) is a standalone desktop application that connects to your running app and gives you a genuinely richer debugging experience: a live component tree you can browse and click through, a network tab showing every request your app makes (handy for debugging the fetch/Axios calls from Networking: Fetch & Axios), and a way to directly inspect what's currently stored in AsyncStorage — extremely useful when tracking down why persisted data (see Local Storage: AsyncStorage) isn't showing what you expect.

The Element Inspector: Debugging Layout Visually

Enabling the Element Inspector (from the Developer Menu) lets you tap directly on any element rendered on screen and see exactly which component it is, along with its resolved style values — the actual padding, margin, width, and flex properties currently being applied. This is by far the fastest way to track down a spacing or alignment bug: rather than guessing which flex/justifyContent/alignItems combination from Flexbox Layout is misbehaving, you tap the misbehaving element and read its computed layout directly.

A Common Real Bug: "Text strings must be rendered within a <Text> component"

This is one of the most common errors newcomers hit, and it comes directly from a rule covered in Core Components: raw text can only ever appear inside a <Text> component — never as a direct child of a <View>. The mistake usually sneaks in through a conditional expression that accidentally evaluates to a plain string or number sitting next to JSX.

// Throws: "Text strings must be rendered within a <Text> component"
function Greeting({ name }) {
  return (
    <View>
      Hello, {name}! // this bare text is NOT inside <Text>
    </View>
  );
}
// Fixed: wrap the text in <Text>
function Greeting({ name }) {
  return (
    <View>
      <Text>Hello, {name}!</Text>
    </View>
  );
}

The same trap shows up with a falsy value rendered directly inside a View — for example {count && <Text>{count}</Text>} when count is 0 renders the literal number 0 as bare text next to the <View>'s other children, triggering the same error. Whenever you see this message, the fix is always the same: find the bare string/number sitting outside a <Text> and wrap it.

React DevTools: Inspecting Component Tree, Props, and State

The React DevTools browser extension — the same one countless React web developers already have installed — also works with React Native. Once connected to your running app, it shows the live component tree, lets you click any component to see its current props and state, and lets you tweak those values on the fly to see how the UI reacts. If you're coming from web React, this is the fastest tool to feel productive with immediately, since the experience is nearly identical.

Note: nothing on this page is a live debugging session — it's a written guide to tools and a real bug pattern you'll encounter in your own project (started back in Installation & Setup), since this site doesn't run a React Native build itself.
Next up: catching bugs before they even reach the Developer Menu, with automated tests. Continue to Testing.