Debugging React Native apps like a Pro in 2023

Debugging React Native apps during development.

React Native has seen an incredible growth in popularity since its introduction. As with any programming language or framework, the need for effective debugging tools is paramount. This article will cover some of the most effective ways to debug React Native applications in 2023.

Browser Developer Tools

One of the most basic, yet powerful tools you have for debugging your React Native applications are the browser developer tools provided by Chrome or Safari. Here’s how to use them:

1. Run Your Application

To begin with, you need to start your React Native application. Open your terminal or command line, navigate to your project directory, and type the following:

npm start

This will start your application’s development server.

2. Enable Debugging

While your application is running, shake your device or press Ctrl + M (or Cmd + D on MacOS). This will open the developer menu. From this menu, select Debug JS Remotely.

Note: If you’re using a physical device, you can shake it to open the developer menu. If you’re using a simulator or emulator, you can use the keyboard shortcuts mentioned above.

Your application will now start running JavaScript code in the development server, and you can debug it using your browser’s developer tools.

3. Open Developer Tools in Your Browser

If you’re using Google Chrome, you can open the developer tools by right-clicking anywhere on the page and selecting Inspect, or by using the Ctrl + Shift + I shortcut (or Cmd + Option + I on MacOS). For Safari, you’ll need to enable the developer tools in the Advanced tab of the browser’s preferences.

Once the developer tools are open, you’ll see a console where you can view any console.log() statements, errors, or warnings that occur in your JavaScript code. You can also interact with your JavaScript and view variables or call functions from the console.

4. Use Breakpoints

For more complex debugging, you might want to use breakpoints. In the Sources tab of the developer tools, you can navigate to your JavaScript files and click on a line number to set a breakpoint. When the execution reaches this line, it will pause, allowing you to inspect the current state of your app at that point in time.

Remember: Debugging like this can make your application run slower because it’s being debugged. Don’t forget to disable remote debugging when you’re done!

5. Disable Debugging

When you’re done, you can disable it by opening the developer menu in your React Native app and selecting Stop Remote JS Debugging. Your app will then return to its normal speed.

React Native Debugger

React Native Debugger is an open-source tool that combines Redux DevTools, React DevTools, and a JavaScript debugger all into one. It’s a standalone desktop application that integrates well with React Native. This tool allows you to inspect your React Native and Redux state, show API requests and responses, and it supports debugging of the JavaScript code directly within the app.

Here’s how you can use React Native Debugger effectively:

1. Installation

Before we get started, make sure you have React Native Debugger installed on your system. You can download it from its GitHub page. Once installed, open it and it will wait for a debugger to connect.

2. Connecting Your App

Next, you will need to connect your React Native app to the React Native Debugger. For that, you’ll need to enable remote debugging in your app.

  • iOS Device: If you’re running the Expo App on iOS, shake your iOS device to reveal the “In-App Developer Menu”.
  • iOS Emulator: If the app is running in the iOS Emulator, use the Device -> Shake option.
  • Android Device: If you’re running the Expo App on Android, shake your Android device to reveal the “In-App Developer Menu”.
  • Android Emulator: If the app is running in Android Emulator, press Cmd+M or Ctrl+M button.

Once you’ve launched the “In-App Developer Menu”, select the “Debug Remote JS” option. Now the React Native Debugger can connect to the app running in Expo Go.

3. Finding the bugs

Once you’ve connected your app to the React Native Debugger, you can start debugging your code. Let’s take an example of a button press event. Say, you have a buttonPressed() function in your App.js file and you want to debug it.

Open the App.js file, scroll down to the buttonPressed() function, and attach a breakpoint to the first line of the method. When you press the button in your app, you will see that the debugger has paused the execution of the code. You can now inspect your variables, step through your code, and understand what’s happening under the hood when the button is pressed.

And that’s it! You’ve successfully set up and used the React Native Debugger with your app. Whether you’re looking for a simple way to debug your components, inspect your Redux state, or debug your JavaScript code, React Native Debugger has you covered.

Reactotron

Reactotron is a macOS, Windows, and Linux app for inspecting your React JS and React Native apps.

Why Reactotron?

If you’re like many developers, you may have relied heavily on the React Native Debugger and an abundance of console.log statements to debug your applications.

While these tools can certainly be effective, they can also lead to clutter and intensive resource usage within your project. This is where Reactotron shines.

Reactotron is a cross-platform application that allows you to automatically track various aspects of your application, such as remote requests and AsyncStorage usage, making the debugging process significantly more streamlined.

1. Installation

To get started with Reactotron, first, install the correct desktop app for your platform from the releases page.

Then, add Reactotron as a development dependency to your React Native project with the following command:

yarn add --dev reactotron-react-native

Now, you’ll need to configure Reactotron. Create a configuration file, typically named ReactotronConfig.js, with the following content:

import Reactotron from 'reactotron-react-native';

Reactotron.configure().useReactNative().connect();

Lastly, import this configuration file from your main application file (App.js or index.js). This allows Reactotron to be initialized whenever your application runs in development mode:

if (__DEV__) {
  import('./config/ReactotronConfig').then(() =>
    console.log('Reactotron Configured')
  );
}

With this setup, you’re ready to start leveraging the power of Reactotron in your bug hunting sessions.

2. Monitoring Network Requests

One of the major benefits of Reactotron is its ability to automatically monitor network requests.

Within the timeline tab of the Reactotron interface, you can observe a chronological log of all operations performed by your application. By clicking on individual network requests, you can inspect the sent data, received responses, used headers, and more.

This feature can be a lifesaver when you’re trying to investigate issues related to API calls, such as overlooked typos or missing headers.

Additionally, Reactotron allows you to copy these responses for further analysis, making it a robust tool for understanding the network behavior of your application.

3. Monitoring AsyncStorage

Reactotron also provides automatic monitoring of AsyncStorage operations.

This can be incredibly valuable in understanding when and how your application is interacting with stored data. By viewing the timing, key, and value of each AsyncStorage operation, you can gain insight into potential issues that may not be immediately evident from your application’s UI or behavior.

For instance, if you observe that no data exists when a certain AsyncStorage.getItem call is made, you might realize that you need to initialize a default value for that item to avoid errors in your application.

4. Advanced Logging

Beyond automatic monitoring, Reactotron also provides an interface for custom logging.

For instance, if you want to log specific errors for network requests, you can use Reactotron.log to send these messages to the Reactotron interface. This can be particularly useful for logging errors that occur during development, while still allowing you to log to a production error monitor when the app is in production mode:

import Reactotron from 'reactotron-react-native';

export const logError = (error) => {
  if (__DEV__) {
    Reactotron.log(error);
  } else {
    // Log to your error monitor in production, like Sentry
  }
};

In this way, Reactotron can act as a filterable, centralized hub for all of your logging information, freeing you from the clutter of console.log statements scattered throughout your code. You can also create more detailed log messages using Reactotron.display, which allows you to specify a name, preview, value, and importance level for each log:

import Reactotron from 'reactotron-react-native';

export const logError = (error) => {
  if (__DEV__) {
    Reactotron.display({
      name: 'ERROR',
      preview: error.name,
      value: error.message,
      important: true,
    });
  } else {
    // Log to your error monitor in production, like Sentry
  }
};

These more granular logs can help you pinpoint and understand complex errors in your application.

5. Custom Commands

Reactotron allows you to define custom commands, which are code snippets that you can run from the Reactotron interface. This can be incredibly useful for tasks that you find yourself performing frequently during development. For instance, you might create a custom command to clear all data from AsyncStorage, saving yourself the trouble of manually clearing individual items or re-installing the app:

Reactotron.onCustomCommand({
  command: 'emptyAsyncStorage',
  handler: () => {
    AsyncStorage.getAllKeys()
      .then((keys) => AsyncStorage.multiRemove(keys))
      .then(() => {
        alert('AsyncStorage cleared.');
      });
  },
  title: 'Clear AsyncStorage',
  description: 'Clears all data from AsyncStorage.',
});

By registering a command, a handler function, and some optional metadata, you can create powerful, reusable tools that significantly speed up your React Native debugging process.

Flipper

Flipper is a versatile platform designed for debugging iOS, Android, and React Native applications. Its primary goal is to become an essential tool for mobile app development on both iOS and Android platforms. Flipper offers a range of valuable features that help developers build and debug their mobile applications more effectively. Here’s a brief overview of its features:

  • Mobile Development Tools: Flipper offers a suite of tools that assist in mobile app development. These include a log viewer, an interactive layout inspector, and a network inspector. The log viewer helps in tracking events and errors in the app, the layout inspector allows you to inspect and modify your UI from the desktop app in real time, and the network inspector helps in monitoring network requests and responses.
  • Plugins: Flipper is designed as a platform, not just a tool. This means it can be extended by creating your own plugins to visualize and debug data from your mobile applications. This makes Flipper highly adaptable to specific use-cases, as developers can tailor it to suit their needs.
  • Open Source: Flipper is open-source and uses an MIT license. This means that the community of developers can contribute to its development. It also allows developers to understand how the built-in plugins work, and they can leverage this knowledge to build their own plugins.

Setting up a React Native application with Flipper involves several steps:

1. Install Flipper

The first step is to download and install Flipper. You can download it from the official Flipper download page. Choose the appropriate version for your operating system and install it as you would any other software.

2. Install React Native

You need to have a React Native project to use with Flipper.

If you don’t have one already, install React Native using the command

npx react-native init MyTestApp

3. Install Dependencies

In your React Native project, you need to install some dependencies to use Flipper. You can add these using yarn or npm. The dependencies are react-native-flipper and @react-native-community/cli-debugger-ui.

To install them, use the commands:

yarn add react-native-flipper @react-native-community/cli-debugger-ui --dev

4. Configure Flipper in React Native

You need to set up Flipper in your React Native application. This involves adding some code in your index.js file. Here is an example of what the setup might look like:

import { AppRegistry } from 'react-native';
import App from './App';
import { name as appName } from './app.json';

if (__DEV__) {
  import('react-native-flipper').then(() =>
    console.log('Flipper is connected!'),
  );
}

AppRegistry.registerComponent(appName, () => App);

5. Run Your React Native Application

Now that you’ve installed and set up Flipper, it’s time to run your React Native application.

Depending on your target platform, use the following command to start your project:

npx react-native run-android or npx react-native run-ios

6. Open Flipper Desktop App

With your React Native application running, open the Flipper desktop application.

You should see your application in the “Connected Apps” list in Flipper.

7. Find bugs!

Now you can start debugging your application!

For example, you can use the “Layout Inspector” to inspect your application’s UI, or the “Network” tab to monitor network requests and responses.

Pro Tip: Use Flipper in conjunction with React DevTools for an enhanced debugging experience.

This is a basic setup and debugging process. Depending on your needs and the complexity of your application, you might need to configure more settings or install additional Flipper plugins. You can find more information and advanced usage examples in the official Flipper documentation.

Frequently Asked Questions (FAQ)

What are the differences between Chrome Developer Tools and React Native Debugger?

Chrome Developer Tools are primarily used for debugging JavaScript code in the browser. They come with features like inspecting DOM, monitoring network requests, profiling JavaScript performance, and more. React Native Debugger, on the other hand, is a standalone app for debugging React Native applications. It includes React Developer Tools, Redux DevTools, and a JavaScript debugger.

When should I use Reactotron over Flipper or vice versa?

Reactotron and Flipper both provide rich features for debugging React Native applications. However, they differ in certain areas. Reactotron offers features like state snapshot management, benchmarking, and custom commands. Flipper provides a more extensive set of built-in plugins for tasks like viewing logs, inspecting network requests, and analyzing application layout. The choice between these two tools often comes down to your specific debugging needs and personal preference.

How does debugging in a React Native application differ from debugging in a regular React application?

Debugging in a React Native application involves dealing with both JavaScript and native code (Java, Kotlin, Objective-C, Swift). This is different from a regular React application, which is typically written only in JavaScript. Additionally, you might need to debug device-specific issues in React Native, which isn’t the case with React on the web.

Can I use these debugging tools with Expo, or do they only work with React Native CLI projects?

Most of the debugging tools mentioned in this guide can be used with both Expo and React Native CLI projects. However, some tools may require additional configuration steps, especially when used with Expo.

Are there any limitations to using these tools for debugging React Native applications?

Yes, like any tool, these debugging tools have their limitations. For instance, while they’re great for debugging JavaScript, they might not help you much when you need to debug native code. Similarly, there might be limitations in debugging third-party libraries, performance issues, or device-specific problems.

Can I use Flipper to debug iOS apps on a Windows machine?

Yes, you can use Flipper to debug iOS apps from a Windows machine. However, to do this, you need to have the iOS app running on a device or simulator that is accessible from the Windows machine. This typically requires a network connection between the two machines.

How do I debug performance issues in a React Native application?

Performance issues can be trickier to debug. They may be due to JavaScript code, native code, or interactions between the two. Tools like the JavaScript profiler in React Native Debugger, the Performance Monitor in React Native, or the Profiler in React Developer Tools can help identify performance bottlenecks.

Can these tools help me to debug third-party libraries used in my React Native project?

Yes, these tools can help you debug issues with third-party libraries in your React Native projects to some extent. However, keep in mind that for some complex or native libraries, you might need to dig into the library’s source code or use native debugging

How can I use Reactotron to monitor network requests in my React Native application?

Reactotron provides automatic network monitoring capabilities. Once configured, it will show a timeline of everything your app does, including all network requests. For each request, you can view the data sent, the response received, and the headers used. This can be particularly useful for identifying typos in queries or missing headers.

Can Reactotron be used to monitor AsyncStorage usage?

Yes, Reactotron can automatically monitor AsyncStorage in your React Native application. This allows you to see when AsyncStorage calls are made, what keys you’re writing to, and what you’re writing. This can be useful for identifying when a key is being accessed before any data has been stored in it.

How can I log custom events in Reactotron?

Reactotron allows you to manually log events or errors. For example, you can create a utility file where you use Reactotron.log to log errors in your development environment. You can also use Reactotron.display to create more detailed messages, including a name for the event, a preview, a value, and an ‘important’ flag.

Wrapping Up

Debugging is a crucial part of the software development process, and having the right tools and knowledge on how to use them can save you hours of frustration. In this article, we’ve covered several powerful tools for React Native applications: Chrome Developer Tools, React Native Debugger, Reactotron, and Flipper.

All these tools have their strengths and offer unique features for efficient debugging:

  • Chrome Developer Tools provide basic but essential features such as console logs, sourcemaps, and breakpoints.
  • React Native Debugger is a standalone app for debugging React Native applications, providing a suite of tools that combines the power of Chrome DevTools with React and Redux DevTools.
  • Reactotron is a desktop application that provides a diverse set of features, including state tracking, API requests monitoring, performance benchmarking, and much more.
  • Flipper is a versatile debugging platform for iOS, Android, and React Native apps that offers a customizable interface with a variety of plugins.

Each one of them may be better suited to different tasks, and many developers will end up using a combination of these tools depending on the specific needs of their project.

The key is to spend time learning and getting comfortable with them, as they will be instrumental in your journey as a React Native developer.

Remember that finding bugs is not just about fixing errors; it’s about understanding why those errors occurred in the first place. With these tools at your disposal, you’ll be better equipped to dive deep into your code, identify issues, and understand your application at a much deeper level.

Stay tuned to our blog at reactnativecentral.com for the latest information, tips, and resources on React Native development.

To further your understanding of React Native, have a look at some of our other articles:

Scroll to Top