Logging & Debugging
Guidelines for tracking application behavior and debugging issues in Expo.
Logging and debugging are essential for maintaining a healthy application. This guide outlines the tools and practices used in this boilerplate to monitor state, network, and errors.
Overview
We use a combination of React Native's built-in console for development, React Query DevTools for network state, and Sentry/Crashlytics for production error tracking.
🏗 Architecture
1. Development Logging
In development mode, we use standard console methods. To prevent logs from cluttering the production environment, always wrap them in if (__DEV__) or use a utility that handles this.
if (__DEV__) {
console.log('App initialized');
}2. Network Logging
Our API service (services/api.ts) is configured to log outgoing requests and parsing errors when in development mode.
// services/api.ts
if (__DEV__) console.log(`[API] ${method} ${url}`);You can also use the React Query DevTools on web or the React Native Debugger to inspect network traffic.
3. State Tracking
- React Query: Tracks the state of your server data. You can observe transitions between
loading,error, andsuccessstates in your components. - Zustand: For global client-side state. You can add middleware to log state transitions during development.
4. Navigation Tracking
The boilerplate uses expo-router. You can track navigation state by listening to router changes in your root layout.
🚀 Usage
Standard Logging
Use the appropriate log level for your messages:
console.log("Debug info"); // General development info
console.warn("Potential issue"); // Non-critical issues
console.error("Critical error"); // Failures that need attentionAPI Errors
Errors from the api service are thrown as ApiError. These should be caught in your mutations or queries:
try {
await api.post('/login', data);
} catch (error) {
if (error instanceof ApiError) {
console.error(`API Error ${error.status}: ${error.message}`);
}
}🛠 Debugging Tools
1. Expo Go & Dev Menu
Shake your device or press d in the terminal to open the Expo Dev Menu. From here, you can:
- Reload the app.
- Toggle the Performance Monitor.
- Open the Element Inspector.
2. Chrome DevTools
When running the app, you can debug JavaScript using Chrome DevTools:
- Open the Dev Menu in your app.
- Select "Debug remote JS".
- A Chrome tab will open where you can set breakpoints and inspect logs.
3. React Query DevTools
To debug network requests and cache state:
- On Web: The devtools are available if configured in
app/_layout.tsx. - On Mobile: Use React Query Monitor.
🔗 Integration Points
Our logging and debugging strategy is integrated with:
- React Query: Captures all network state transitions and cache hits/misses.
- Expo Router: Tracks navigation events and route parameters.
- Zustand: Monitors global client state changes (via devtools).
- Firebase: Logs push notification reception and token updates.
- App Lifecycle: Using Expo's
AppStateto log when the app moves to background or returns to active.
🚨 Production Logging
For production monitoring, we recommend integrating the following services:
Sentry (Error Tracking)
Sentry captures crashes and JavaScript errors in real-time.
- Install:
npx expo install @sentry/react-native - Configure: Add to
app.jsonplugins:"plugins": ["@sentry/react-native/expo"] - Initialize: In your root
_layout.tsx:import * as Sentry from '@sentry/react-native'; Sentry.init({ dsn: 'YOUR_SENTRY_DSN', debug: __DEV__, });
Firebase Crashlytics
For native-level crash reporting.
- Install:
npx expo install expo-firebase-crashlytics - Configure: Ensure
google-services.jsonandGoogleService-Info.plistare in your project root.
💡 Best Practices
- Remove Logs in Production: Use
babel-plugin-transform-remove-consolein yourbabel.config.jsto automatically strip console logs from production builds. - No Sensitive Data: Never log passwords, tokens, or PII (Personally Identifiable Information).
- Contextual Messages: Include enough context in your logs to identify where and why an event happened.
- Bad:
console.log(data) - Good:
console.log('[AuthStore] Token refreshed:', data.id)
- Bad:
