Paramclasses Academy - Blog

Tutorials Details

←
Post 32 of 39
→

How to Debug React Native Apps and Fix Common Errors ?

How to Debug React Native Apps and Fix Common Errors ?

November 5, 2026

1. Introduction

While developing mobile applications, developers frequently encounter errors such as application crashes, incorrect UI behavior, missing components, navigation problems, and API failures.

Debugging is the process of identifying, analyzing, and fixing these problems.

React Native provides several debugging tools that help developers understand what is happening inside their applications.

In this tutorial, we will learn how to debug React Native applications using React Native DevTools, console logs, breakpoints, LogBox, and Android Studio Logcat.

We will also build a practical Debugging Lab application and fix common programming mistakes.

2. What Is Debugging?

Debugging is the process of finding and correcting errors (bugs) in a software application.

A bug can affect:

  • Application startup.

  • Screen navigation.

  • UI rendering.

  • State management.

  • API requests.

  • User interactions.

  • Application performance.

Example

Suppose a button should increase a counter, but the displayed value never changes.

This is a programming problem that requires debugging.

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

const increaseCount = () => {
  count = count + 1;
};

The above code is incorrect because React state should not be modified directly.

Correct implementation:

const increaseCount = () => {
  setCount((previousCount) => previousCount + 1);
};

Now React receives the state update and renders the updated value.

3. Types of Errors in React Native

Understanding different types of errors makes debugging easier.

3.1 Syntax Errors

Syntax errors occur when JavaScript code does not follow the correct language syntax.

Example:

const name = "Rahul"
console.log(name

The closing parenthesis is missing.

Correct code:

const name = "Rahul";

console.log(name);

3.2 Runtime Errors

Runtime errors occur while the application is executing.

Example:

const student = undefined;

console.log(student.name);

This causes an error because student is undefined.

Correct code:

const student = undefined;

console.log(student?.name);

Optional chaining prevents an error when accessing a property on a nullish value.

3.3 Logical Errors

Logical errors occur when code executes successfully but produces an incorrect result.

Example:

const total = 100;
const discount = 20;

const finalPrice = total + discount;

The code runs, but the calculation is incorrect.

Correct code:

const finalPrice = total - discount;

3.4 UI Errors

UI errors occur when application components do not display or behave as expected.

Examples:

  • Incorrect alignment.

  • Missing images.

  • Text overflowing the screen.

  • Buttons not responding.

  • Incorrect component dimensions.

3.5 Network Errors

Network errors occur when an application cannot communicate successfully with a server or API.

Common reasons include:

  • No internet connection.

  • Incorrect API URL.

  • Server unavailable.

  • Invalid response.

  • Request timeout.

  • Authentication failure.

4. Important React Native Debugging Tools

React Native and Expo provide several useful debugging tools.

Tool Purpose
React Native DevTools Debug JavaScript and inspect application behavior
Console Display logs and inspect values
Sources Inspect code and set breakpoints
LogBox Display errors and warnings
React Components Inspector Inspect components, props and state
Profiler Analyze component rendering
Android Studio Logcat Inspect Android native logs
Expo CLI View development logs

 

 

Important: React Native DevTools is the recommended modern JavaScript debugging experience. Older remote JavaScript debugging workflows are deprecated. <Cite refs={["turn102158search0","turn102158search1","turn102158search2"]}/>

5. Create a React Native Project

Open your terminal:

npx create-expo-app@latest DebuggingLab --template blank

Navigate into the project:

cd DebuggingLab

Start the development server:

npx expo start

Open your application using Expo Go or an appropriate development build.

6. Open the Developer Menu

The Developer Menu provides access to important development features.

On Android

You can open the Developer Menu using:

  • Shake your physical device.

  • Press Ctrl + M on Windows/Linux Android emulators.

  • Press Cmd + M on macOS Android emulators.

  • Press M in the terminal running Expo CLI.

You can also execute:

adb shell input keyevent 82

Important Developer Menu Options

  1. Reload – Reload the application.

  2. Open DevTools – Open React Native DevTools.

  3. Toggle Element Inspector – Inspect UI elements.

  4. Toggle Performance Monitor – View performance information.

  5. Fast Refresh – Update application code during development.

The exact available options depend on your Expo and React Native version. <Cite refs={["turn102158search0","turn102158search1"]}/>

7. Open React Native DevTools

React Native DevTools helps developers inspect application behavior.

Follow these steps:

  1. Start the React Native application.

  2. Open the terminal running Expo.

  3. Press J.

  4. React Native DevTools will open.

  5. Select the Console tab.

  6. Inspect application logs and errors.

You can also open DevTools through the Developer Menu.

Important DevTools Panels

Console

Displays logs, warnings, errors, and JavaScript values.

Sources

Displays application source code and supports breakpoints.

Components

Helps inspect React components, props, and state.

Profiler

Helps analyze React component rendering.

Network

In supported Expo debugging setups, helps inspect network activity.

The available panels depend on the runtime and development environment. <Cite refs={["turn102158search1","turn102158search2"]}/>

8. Debugging with console.log()

The simplest debugging technique is using console methods.

console.log()

Displays normal messages.

const username = "Rahul";

console.log("Username:", username);

console.warn()

Displays warning messages.

console.warn("Please check the user input.");

console.error()

Displays error messages.

console.error("Unable to connect to server.");

console.table()

Displays arrays and objects in a table when supported by the debugging console.

const students = [
  {
    id: 1,
    name: "Rahul",
    course: "React Native",
  },
  {
    id: 2,
    name: "Amit",
    course: "Java",
  },
];

console.table(students);

Practical Debugging Example

const calculateTotal = (price, quantity) => {
  console.log("Price:", price);
  console.log("Quantity:", quantity);

  const total = price * quantity;

  console.log("Total:", total);

  return total;
};

calculateTotal(500, 3);

Expected output:

Price: 500
Quantity: 3
Total: 1500

9. Debugging with Breakpoints

A breakpoint pauses program execution at a specific line.

It allows developers to inspect variables and understand how the application executes code.

Example

const calculateDiscount = (price, discount) => {
  const discountAmount = price * discount / 100;

  debugger;

  const finalPrice = price - discountAmount;

  return finalPrice;
};

console.log(calculateDiscount(1000, 10));

When execution reaches debugger, the application pauses if DevTools is connected.

Steps to Use Breakpoints

  1. Open React Native DevTools.

  2. Select the Sources panel.

  3. Open your JavaScript file.

  4. Click the line number where you want to pause execution.

  5. Perform the action in your application.

  6. Inspect local variables and the call stack.

  7. Use the step controls to execute the code line by line.

Remove temporary debugger statements before production.

10. Understand LogBox

LogBox displays errors and warnings inside a React Native application during development.

Example: Display a Warning

console.warn("This is a debugging warning.");

Example: Display an Error

console.error("This is a debugging error.");

Common LogBox Messages

  • Undefined variable.

  • Invalid component property.

  • Missing list key.

  • JavaScript runtime error.

  • Deprecated API warning.

Do not ignore warnings without understanding their cause.

React Native's debugging tools are development features and are not available in release builds. <Cite refs={["turn102158search0","turn102158search8"]}/>

11. Debugging with Android Studio Logcat

Sometimes an application crashes because of an Android native error rather than a JavaScript error.

Android Studio Logcat helps developers inspect native logs.

Steps

  1. Open Android Studio.

  2. Open your Android application or connect a running device.

  3. Start the application.

  4. Open the Logcat window.

  5. Select the running application process.

  6. Filter errors using the Error log level.

  7. Inspect the relevant stack trace.

You can also use the terminal:

adb logcat

To filter common React Native messages:

adb logcat "*:S" ReactNative:V ReactNativeJS:V

Native logs are particularly useful for investigating crashes and native module problems. <Cite refs={["turn102158search3","turn102158search5"]}/>

12. Create the Debugging Lab Application

Now we will build a practical application demonstrating common debugging techniques.

Our Debugging Lab will contain:

  • Counter functionality.

  • Student list.

  • Input validation.

  • Debugging console messages.

  • Error simulation.

  • Correct state updates.

Project Structure

DebuggingLab/
│
├── App.js
├── package.json
└── node_modules/

13. Complete App.js Code

Open App.js and add the following code:

import React, { useState } from "react";

import {
  View,
  Text,
  TextInput,
  Pressable,
  FlatList,
  StyleSheet,
  Alert,
  ScrollView,
} from "react-native";

export default function App() {
  const [count, setCount] = useState(0);

  const [name, setName] = useState("");

  const [students, setStudents] = useState([
    {
      id: "1",
      name: "Rahul",
      course: "React Native",
    },
    {
      id: "2",
      name: "Amit",
      course: "Java",
    },
  ]);

  // Counter functionality
  const increaseCount = () => {
    console.log("Previous count:", count);

    setCount((previousCount) => previousCount + 1);

    console.log("Counter update requested.");
  };

  const decreaseCount = () => {
    if (count > 0) {
      setCount((previousCount) => previousCount - 1);
    } else {
      Alert.alert("Warning", "Counter cannot go below zero.");
    }
  };

  // Add student
  const addStudent = () => {
    if (!name.trim()) {
      console.warn("Student name is empty.");

      Alert.alert(
        "Validation Error",
        "Please enter a student name."
      );

      return;
    }

    const newStudent = {
      id: Date.now().toString(),
      name: name.trim(),
      course: "React Native",
    };

    console.log("Adding student:", newStudent);

    setStudents((previousStudents) => [
      ...previousStudents,
      newStudent,
    ]);

    setName("");
  };

  // Simulate an error
  const simulateError = () => {
    try {
      throw new Error(
        "This is a sample debugging error."
      );
    } catch (error) {
      console.error("Debugging Error:", error.message);

      Alert.alert(
        "Debugging Lab",
        error.message
      );
    }
  };

  // Render student
  const renderStudent = ({ item }) => (
    <View style={styles.studentCard}>
      <Text style={styles.studentName}>
        {item.name}
      </Text>

      <Text style={styles.courseText}>
        {item.course}
      </Text>
    </View>
  );

  return (
    <ScrollView
      style={styles.container}
      contentContainerStyle={styles.content}
    >
      <Text style={styles.heading}>
        React Native Debugging Lab
      </Text>

      <Text style={styles.subtitle}>
        Learn Debugging with Practical Examples
      </Text>

      {/* Counter Section */}
      <View style={styles.card}>
        <Text style={styles.sectionTitle}>
          Counter Debugging
        </Text>

        <Text style={styles.counter}>
          {count}
        </Text>

        <View style={styles.buttonRow}>
          <Pressable
            style={styles.primaryButton}
            onPress={increaseCount}
          >
            <Text style={styles.buttonText}>
              Increase
            </Text>
          </Pressable>

          <Pressable
            style={styles.dangerButton}
            onPress={decreaseCount}
          >
            <Text style={styles.buttonText}>
              Decrease
            </Text>
          </Pressable>
        </View>
      </View>

      {/* Student Section */}
      <View style={styles.card}>
        <Text style={styles.sectionTitle}>
          Student Management
        </Text>

        <TextInput
          style={styles.input}
          placeholder="Enter student name"
          value={name}
          onChangeText={setName}
        />

        <Pressable
          style={styles.successButton}
          onPress={addStudent}
        >
          <Text style={styles.buttonText}>
            Add Student
          </Text>
        </Pressable>

        <Text style={styles.listHeading}>
          Student List
        </Text>

        <FlatList
          data={students}
          keyExtractor={(item) => item.id}
          renderItem={renderStudent}
          scrollEnabled={false}
        />
      </View>

      {/* Error Simulation */}
      <View style={styles.card}>
        <Text style={styles.sectionTitle}>
          Error Simulation
        </Text>

        <Text style={styles.description}>
          Press the button to generate a sample error
          and inspect the console.
        </Text>

        <Pressable
          style={styles.dangerButton}
          onPress={simulateError}
        >
          <Text style={styles.buttonText}>
            Generate Test Error
          </Text>
        </Pressable>
      </View>
    </ScrollView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#F1F5F9",
  },

  content: {
    padding: 20,
    paddingTop: 60,
    paddingBottom: 40,
  },

  heading: {
    fontSize: 24,
    fontWeight: "bold",
    color: "#172554",
  },

  subtitle: {
    color: "#64748B",
    marginBottom: 22,
    marginTop: 5,
  },

  card: {
    backgroundColor: "#FFFFFF",
    padding: 18,
    borderRadius: 14,
    marginBottom: 18,
    elevation: 2,
  },

  sectionTitle: {
    fontSize: 18,
    fontWeight: "bold",
    color: "#1E293B",
    marginBottom: 15,
  },

  counter: {
    fontSize: 40,
    fontWeight: "bold",
    textAlign: "center",
    color: "#2563EB",
    marginVertical: 15,
  },

  buttonRow: {
    flexDirection: "row",
    gap: 10,
  },

  primaryButton: {
    backgroundColor: "#2563EB",
    padding: 13,
    borderRadius: 9,
    flex: 1,
    alignItems: "center",
  },

  dangerButton: {
    backgroundColor: "#DC2626",
    padding: 13,
    borderRadius: 9,
    flex: 1,
    alignItems: "center",
  },

  successButton: {
    backgroundColor: "#059669",
    padding: 13,
    borderRadius: 9,
    alignItems: "center",
  },

  buttonText: {
    color: "#FFFFFF",
    fontWeight: "bold",
  },

  input: {
    backgroundColor: "#F8FAFC",
    borderWidth: 1,
    borderColor: "#CBD5E1",
    borderRadius: 9,
    padding: 13,
    marginBottom: 12,
  },

  listHeading: {
    fontSize: 16,
    fontWeight: "bold",
    marginTop: 20,
    marginBottom: 10,
  },

  studentCard: {
    padding: 13,
    backgroundColor: "#F1F5F9",
    borderRadius: 9,
    marginBottom: 9,
  },

  studentName: {
    fontWeight: "bold",
    fontSize: 16,
    color: "#1E293B",
  },

  courseText: {
    color: "#64748B",
    marginTop: 4,
  },

  description: {
    color: "#64748B",
    marginBottom: 15,
  },
});

14. Test the Debugging Lab

Follow these steps:

  1. Start the application.

  2. Open the Counter Debugging section.

  3. Press Increase.

  4. Observe the updated counter.

  5. Open React Native DevTools.

  6. Check the Console panel.

  7. Observe the counter log messages.

  8. Enter a student name.

  9. Press Add Student.

  10. Verify the new student appears in the list.

  11. Press Add Student without entering a name.

  12. Observe the validation warning.

  13. Press Generate Test Error.

  14. Inspect the error message in the console.

This application demonstrates how to use logs, validation, state updates, and error handling during development.

15. Common React Native Errors and Their Solutions

Error 1: Unable to Resolve Module

Example:

Unable to resolve module 'some-library'

Reason: The package may not be installed or its import path may be incorrect.

Solution:

Check the package installation:

npm install some-library

For Expo-compatible native dependencies, use:

npx expo install some-library

Restart the development server if required.

Error 2: Cannot Read Property of Undefined

Example:

const user = undefined;

console.log(user.name);

Solution:

console.log(user?.name ?? "Unknown User");

Always validate data before accessing its properties.

Error 3: Missing List Key

Incorrect code:

students.map((student) => (
  <Text>{student.name}</Text>
));

Correct code:

students.map((student) => (
  <Text key={student.id}>
    {student.name}
  </Text>
));

For FlatList, provide a stable keyExtractor.

Error 4: State Not Updating

Incorrect code:

count = count + 1;

Correct code:

setCount((previous) => previous + 1);

Do not directly modify React state.

Error 5: Application Shows a Blank Screen

Possible reasons:

  • JavaScript runtime error.

  • Incorrect component export.

  • Invalid JSX.

  • Incorrect navigation configuration.

  • Failed application initialization.

Solution:

  1. Check the Expo terminal.

  2. Open LogBox.

  3. Inspect React Native DevTools Console.

  4. Verify imports and exports.

  5. Review the stack trace.

  6. Fix the first relevant error and reload.

Error 6: API Request Failed

Incorrect or unreachable API endpoint:

const response = await fetch(
  "https://example.invalid/api/students"
);

Better error handling:

const fetchStudents = async () => {
  try {
    const response = await fetch(
      "https://your-api-domain.com/students"
    );

    if (!response.ok) {
      throw new Error(
        `HTTP Error: ${response.status}`
      );
    }

    const data = await response.json();

    console.log("Students:", data);

  } catch (error) {
    console.error("API Error:", error.message);
  }
};

Always verify the URL, internet connectivity, server status, and response format.

Error 7: Metro Bundler Cache Problems

Sometimes an application continues displaying outdated or unexpected results.

Try clearing the Expo cache:

npx expo start -c

This clears the Metro bundler cache and starts the development server again.

Error 8: Android Application Crashes

Possible reasons:

  • Native module error.

  • Incorrect Android configuration.

  • Memory issue.

  • Native dependency incompatibility.

Solution:

Check Android Studio Logcat and inspect the native crash information.

16. Debugging React Native Navigation

Navigation errors can occur when a screen name is incorrect or navigation is triggered before the navigator is ready.

Example:

navigation.navigate("HomeScreen");

Check that HomeScreen is registered with exactly the same name in your navigator.

Also verify that the screen receives the expected navigation props or uses the appropriate navigation hook.

17. Debugging React Hooks

React Hooks must follow the Rules of Hooks.

Incorrect code:

if (true) {
  const [count, setCount] = useState(0);
}

Correct code:

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

if (count > 5) {
  console.log("Counter exceeded five.");
}

Call Hooks at the top level of React function components or custom Hooks, not inside conditions, loops, or nested functions.

18. Debugging API and Network Requests

When working with REST APIs, inspect:

  • Request URL.

  • HTTP method.

  • Request headers.

  • Request body.

  • HTTP status code.

  • Response data.

  • Error messages.

Example:

const getData = async () => {
  try {
    console.log("Starting API request...");

    const response = await fetch(
      "https://jsonplaceholder.typicode.com/users"
    );

    console.log("Status:", response.status);

    if (!response.ok) {
      throw new Error("API request failed.");
    }

    const data = await response.json();

    console.log("API Response:", data);

  } catch (error) {
    console.error("Network Error:", error.message);
  }
};

This approach makes it easier to identify whether the problem comes from the server, request, or response processing.

19. Best Practices for Debugging

  1. Read the complete error message.

  2. Inspect the first relevant stack trace.

  3. Use meaningful console messages.

  4. Use breakpoints for complex problems.

  5. Reproduce the error consistently.

  6. Fix one problem at a time.

  7. Test the application after each fix.

  8. Keep dependencies compatible with your Expo SDK.

  9. Remove temporary debugging statements before production.

  10. Use native logs when JavaScript logs are insufficient.

  11. Test on both emulator and physical devices.

  12. Avoid hiding errors without understanding their cause.

20. Debugging Checklist

Before completing a React Native application, verify:

  • No JavaScript syntax errors.

  • No unexpected runtime errors.

  • All required packages are installed.

  • All imports and exports are correct.

  • React state updates correctly.

  • Navigation works properly.

  • API requests handle errors.

  • Lists use stable keys.

  • Images load correctly.

  • Application works on Android devices.

  • Native logs have been checked for relevant crashes.

  • Debugging-only code has been removed.

21. Conclusion

In this tutorial, we learned how to debug React Native applications and fix common programming errors.

We explored React Native DevTools, Developer Menu, LogBox, console methods, breakpoints, and Android Studio Logcat.

We also built a practical Debugging Lab application and learned how to fix common issues involving state management, list keys, API requests, imports, navigation, and runtime errors.

Debugging is an essential skill for every React Native developer. Learning these techniques will help you develop more reliable, stable, and maintainable mobile applications.

22. Frequently Asked Questions

Q1. What is debugging in React Native?

Debugging is the process of identifying and fixing errors in React Native applications.

Q2. What is React Native DevTools?

It is the modern debugging environment used to inspect JavaScript execution, components, logs, and application behavior.

Q3. How do I open React Native DevTools in Expo?

Start your Expo project and press J in the terminal running Expo CLI.

Q4. What is LogBox?

LogBox displays runtime errors and warnings during development.

Q5. What is a breakpoint?

A breakpoint pauses program execution at a selected line so developers can inspect variables and execution flow.

Q6. What is Android Studio Logcat?

Logcat is an Android logging tool used to inspect application and system messages.

Q7. How do I clear the Metro cache?

Run:

npx expo start -c

Q8. Can I debug React Native applications in production mode?

Development debugging tools such as LogBox and the Dev Menu are disabled in release builds. Production applications generally require appropriate crash reporting and monitoring tools.


Official Documentation

  1. React Native Debugging Basics: https://reactnative.dev/docs/debugging

  2. React Native DevTools: https://reactnative.dev/docs/react-native-devtools

  3. Expo Debugging Tools: https://docs.expo.dev/debugging/tools/

  4. Expo Runtime Errors: https://docs.expo.dev/debugging/runtime-issues/

  5. Expo Logs: https://docs.expo.dev/workflow/logging/

  6. React Native Native Code Debugging: https://reactnative.dev/docs/debugging-native-code

  7. React Rules of Hooks: https://react.dev/reference/rules/rules-of-hooks

End of Tutorial 33 – Param Classes React Native Tutorial Series

←
Post 32 of 39
→