1.0.7 • Published 5 months ago

@corrbo/react-native-dev-console v1.0.7

Weekly downloads
-
License
ISC
Repository
-
Last release
5 months ago

React Native Dev Console

A simple in-app developer console for React Native applications that allows viewing logs, network requests, and developer tools in production environments.

Example

Dev Console in action

Features

  • Log Viewer - View log, warn, error, and info logs with optional tags for filtering.
  • Network Inspector - Monitor HTTP traffic (powered by react-native-network-logger).
  • Custom Tab - Extend functionality with custom developer toggles and environment configuration.
  • Floating Button - Activate the console programmatically or through specific runtime conditions.
  • Production-ready - Designed to work in release builds and safe for production use.

Installation

1. Install the library

npm install react-native-dev-console

2. Install peer dependencies (if not already installed)

npm install react-native-reanimated react-native-gesture-handler react-native-safe-area-context 

For iOS:

npx pod-install 

Quick Start

1. Wrap your application

<GestureHandlerRootView>
  <SafeAreaProvider>
    <Console>
      <App/>
    </Console>
  </SafeAreaProvider>
</GestureHandlerRootView>

File Structure

Recommended structure for custom Dev Console logic:

src/configs/DevConsole 
├── CustomTab.tsx # Custom tab with toggles and versioning (optional) 
├── init.ts # Initialization logic for Dev Console 
└── types.ts # Dev Console store types

init.ts

import {version} from '../../../package.json'
import {LocalStorageService, LSKeys} from 'services/LocalStorage'

const isDevelop = process.env.NODE_ENV === 'development'

const store = LocalStorageService.getString(LSKeys.LSDevConsoleStore) || `{"devConsoleEnabled": ${isDevelop}}`
const parsedStore = JSON.parse(store)

export const ConsoleService = {
  store: {
    ...parsedStore,
    isDevUrl: parsedStore?.isDevUrl ?? isDevelop,
    version: parsedStore?.version ?? version,
  },
  onSetStore: (newStore: any) => {
    console.log({newStore})
    LocalStorageService.set(LSKeys.LSDevConsoleStore, JSON.stringify(newStore))
  },
}

types.ts

export interface IDevSettingsStore {
  isDevUrl: boolean
  version: string
} 

CustomTab Component

import {ICustomTabProps} from 'react-native-dev-console'
import {Button, StyleSheet, Switch, Text, TextInput, View} from 'react-native'
import React, {useState} from 'react'

export const CustomTab: ICustomTabProps = ({store, setKey}) => {
  const [version, setVersion] = useState(store.version)
  return (
    <View style={styles.container}>
      <View style={styles.item}>
        <Text style={{color: '#fff'}}>Dev Url Api</Text>
        <Switch
          value={store.isDevUrl}
          onChange={() => setKey('isDevUrl', !store.isDevUrl, true)}
        />
      </View>
      <View style={styles.item}>
        <TextInput
          style={{color: '#fff', flex: 1}}
          placeholder={'Version'}
          value={version}
          placeholderTextColor={'#b4b4b4'}
          onChangeText={text => setVersion(text)}
          keyboardType={'numeric'}
        />
        <Button
          title={'Submit'}
          onPress={() => setKey('version', version, false)}
        />
      </View>
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    width: '100%',
    paddingHorizontal: 16,
    paddingBottom: 24,
  },
  item: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    borderBottomWidth: 1,
    borderBottomColor: '#727272',
    paddingBottom: 5,
  },
})

The CustomTab component receives the following props:

export interface ICustomTabProps {
  store: Record<string, any>
  setKey: (key: string, value: any, reload?: boolean) => void
} 
PropTypeDescription
storeRecord<string, any>Current state of the Dev Console store
setKey(key: string, value: any, reload?: boolean) => voidUpdates the store. When persist is true, reload App

Console Component Props

PropTypeDescriptionRequired
childrenReact.ReactNodeYour app root wrapped with the Dev ConsoleYes
CustomTabICustomTabPropsOptional tab with custom settings and togglesNo
button{ style?: StyleProp, content?: React.ReactNode }Customizes the floating buttonNo
button.styleStylePropStyle override for the floating buttonNo
button.contentReact.ReactNodeCustom content (icon/text) for the floating buttonNo

Dev Console Methods

The Console object exposes global functions for programmatic access:

ts Console.enable() Console.log(message: string, tag?: string) Console.error(message: string, tag?: string) Console.info(message: string, tag?: string) Console.warn(message: string, tag?: string)

All logs appear in the Logs tab of the Dev Console.

MethodDescription
Console.enable()Opens the Dev Console manually
Console.log()Adds a standard log message with optional tag for filtering
Console.error()Adds an error message (highlighted in red)
Console.info()Adds an informational message (highlighted in blue)
Console.warn()Adds a warning message (highlighted in yellow)

Example Usage

Console.enable()
Console.log('User logged in', 'Auth')
Console.error('Failed to fetch user data', 'API') 

Example: Dynamic API URL Switching

Use the isDevUrl flag to switch between development and production API endpoints at runtime:

src/configs/DevConsole/init.ts

import {version} from '../../../package.json';
import {LocalStorageService, LSKeys} from 'services/LocalStorage';

const isDevelop = process.env.NODE_ENV === 'development';
const stored = LocalStorageService.getString(LSKeys.LSDevConsoleStore);
const parsed = stored ? JSON.parse(stored) : {};

export const ConsoleService = {
  store: {
    isDevUrl: parsed.isDevUrl ?? isDevelop,
    version: parsed.version ?? version,
  },
  onSetStore: (newStore: any) => {
    LocalStorageService.set(LSKeys.LSDevConsoleStore, JSON.stringify(newStore));
  },
};

services/Api.ts

import axios from 'axios';
import {ConsoleService} from 'src/configs/DevConsole/init';

const DEV_BASE_URL = 'https://dev.api.myapp.com/';
const PROD_BASE_URL = 'https://api.myapp.com/';

export const api = axios.create({
  baseURL: ConsoleService.store.isDevUrl ? DEV_BASE_URL : PROD_BASE_URL,
});

// Update the baseURL dynamically when the flag changes
ConsoleService.onSetStore = (store) => {
  api.defaults.baseURL = store.isDevUrl ? DEV_BASE_URL : PROD_BASE_URL;
};

License

MIT License - free for personal and commercial use.