Skip to main content

Handling App Configuration

1. Using Config Files

File Type Usage Notes
app.json {"expo": {"name": "MyApp", "slug": "my-app"}} Expo configuration file
app.config.js module.exports = { name: 'MyApp', version: '1.0.0' }; JavaScript config for Expo
metro.config.js module.exports = { resolver: { ... } }; Metro bundler configuration
babel.config.js module.exports = { presets: ['module:@react-native/babel-preset'] }; Babel configuration

Example: app.json configuration

{
  "expo": {
    "name": "MyApp",
    "slug": "my-app",
    "version": "1.0.0",
    "platforms": [
      "ios",
      "android",
      "web"
    ],
    "ios": {
      "bundleIdentifier": "com.myapp"
    },
    "android": {
      "package": "com.myapp"
    }
  }
}

Example: metro.config.js setup

const { getDefaultConfig } = require('@expo/metro-config');

const config = getDefaultConfig(__dirname);

config.resolver.assetExts.push('cjs');

module.exports = config;

2. Managing API Keys Securely

Approach Description Notes
Environment Variables process.env.API_KEY Use .env files with react-native-config
Secure Storage react-native-keychain Store sensitive keys in secure OS keychain
Backend Proxy API calls through backend server Never expose keys in client-side code

Example: Using react-native-config

import Config from 'react-native-config'

const apiKey = Config.API_KEY
Note: Never commit API keys to version control. Use .env files and ignore them in .gitignore.
Warning: Keys in client-side code can be extracted from APK/IPA files. Always prefer backend proxies for sensitive operations.

3. Implementing Feature Flags

Feature Flag Value Description
featureA.enabled false Enables or disables Feature A
featureB.enabled true Enables or disables Feature B

Example: Using Feature Flags in React Native

import { Platform } from 'react-native';

const isFeatureAEnabled = () => {
  // Example logic to check feature flag
  return Platform.OS === 'android'; // or fetch from config
};

export default function MyComponent() {
  return (
    <View>
      {isFeatureAEnabled() ? <FeatureA /> : <FeatureB />}
    </View>
  );
}
Note: Feature flags can be managed via remote config services like Firebase Remote Config or AWS Amplify.

4. Using Remote Config

Property Description Default Value Notes
remoteConfig.fetch Fetches remote config values from the server N/A Must be called before accessing config values
remoteConfig.getValue Retrieves a specific config value by key N/A Returns a RemoteConfigValue object
remoteConfig.setDefaults Sets default values for config keys None Used to define fallbacks when remote values are not available

Example: Fetching and Using Remote Config

import { RemoteConfig } from '@react-native-firebase/remote-config';

const fetchConfig = async () => {
  try {
    await RemoteConfig().fetch();
    const config = RemoteConfig().getAll();
    console.log('Remote Config Values:', config);
  } catch (error) {
    console.error('Failed to fetch remote config:', error);
  }
};

fetchConfig();

Example: Setting Default Values

import { RemoteConfig } from '@react-native-firebase/remote-config';

RemoteConfig().setDefaults({
  feature_flag: false,
  welcome_message: 'Welcome to our app!'
});
Note: Remote Config values are cached and updated periodically. Ensure to call fetch() regularly to get the latest values.
Warning: Remote Config is not supported in all environments. Always check for availability before using.

Key Features of Remote Config

  • Fetches configuration values from Firebase
  • Supports default values for fallbacks
  • Allows real-time updates without app store releases

5. Handling Build Configurations

Configuration Description Usage
buildType Defines the type of build (debug, release) "debug" or "release"
versionCode Android version code for app store Integer value
versionName Human-readable version name "1.0.0"
bundleIdentifier Unique identifier for iOS app com.example.app

Example: Build Configuration in Gradle

android {
    compileSdkVersion 33
    defaultConfig {
        applicationId "com.example.app"
        minSdkVersion 21
        targetSdkVersion 33
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        debug {
            debuggable true
        }
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
        }
    }
}

Example: iOS Build Configuration

let config = Bundle.main.infoDictionary
let version = config?["CFBundleShortVersionString"] as? String ?? "Unknown"
let build = config?["CFBundleVersion"] as? String ?? "Unknown"

6. Setting Up Multiple Environments

Example: Environment Configuration with .env Files

// .env.development
REACT_NATIVE_API_URL=https://dev-api.example.com
REACT_NATIVE_LOG_LEVEL=debug

// .env.production
REACT_NATIVE_API_URL=https://api.example.com
REACT_NATIVE_LOG_LEVEL=error
Environment Configuration File Key Variables Notes
development .env.development REACT_NATIVE_API_URL, REACT_NATIVE_LOG_LEVEL Used during local development and debugging
production .env.production REACT_NATIVE_API_URL, REACT_NATIVE_LOG_LEVEL Used for the final build and deployment
Note: Environment variables are loaded at build time and cannot be changed at runtime in a React Native app.
Warning: Never commit sensitive environment files (e.g., .env) to version control.

7. Configuring Build Settings

Setting Description Default Value Notes
buildType Specifies the build type (debug or release) debug Used during build process to determine optimization and debugging features
signingConfig Configuration for signing the app (for release builds) null Required for publishing to app stores
minSdkVersion Minimum Android SDK version required to run the app 21 Must be set to a valid SDK version number
targetSdkVersion Target Android SDK version for the app 33 Should match the latest stable Android SDK version

Example: build.gradle (app level)

android {
    compileSdk 33

    defaultConfig {
        applicationId "com.example.myapp"
        minSdkVersion 21
        targetSdkVersion 33
        versionCode 1
        versionName "1.0"
    }

    buildTypes {
        debug {
            signingConfig null
        }
        release {
            signingConfig signingConfigs.release
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
        }
    }
}

8. Using Native Configuration

Example: Accessing native configuration in React Native

import { Platform } from 'react-native';

const config = {
  isIOS: Platform.OS === 'ios',
  isAndroid: Platform.OS === 'android',
  version: Platform.Version,
  userAgent: Platform.constants?.UserAgent || 'N/A'
};

console.log(config);
Property Description Values
Platform.OS Operating system identifier 'ios', 'android'
Platform.Version OS version number string
Platform.constants Native constants (iOS only) object
Note: On Android, Platform.constants is not available. Use NativeModules for Android-specific values.

Example: Reading from AndroidManifest.xml

import { NativeModules } from 'react-native';

const { BuildConfig } = NativeModules;

if (BuildConfig) {
  console.log('Build Type:', BuildConfig.BUILD_TYPE);
  console.log('Is Debug:', BuildConfig.DEBUG);
}

Example: Reading from Info.plist (iOS)

import { NativeModules } from 'react-native';

const { NSBundle } = NativeModules;

if (NSBundle) {
  const bundleId = NSBundle.bundleIdentifier;
  const version = NSBundle.bundleVersion;
  console.log('Bundle ID:', bundleId);
  console.log('Version:', version);
}

9. Managing App Constants

Constant Value Description
APP_NAME "MyReactNativeApp" Name of the application
API_BASE_URL "https://api.example.com" Base URL for API calls
DEBUG_MODE true Enables debug logging in development

Example: Using Constants in Code

import { API_BASE_URL } from './constants';\n\nconst fetchData = async () => {\n  const response = await fetch(\`${API_BASE_URL}/data\`);\n  return response.json();\n};
Note: Constants should be defined in a centralized file to ensure consistency across the app.

10. Implementing Dynamic Configuration

Configuration Source Description Usage
Environment Variables Used for runtime configuration values process.env.REACT_NATIVE_CONFIG_VALUE
Remote Config Fetches configuration from a remote server RemoteConfig.fetch()
Local Storage Stores configuration in device storage AsyncStorage.setItem('config', JSON.stringify(config))

Example: Using Environment Variables

const config = {
  apiUrl: process.env.REACT_NATIVE_API_URL || 'https://api.example.com',
  debugMode: process.env.REACT_NATIVE_DEBUG === 'true'
};

export default config;

Example: Fetching Remote Config

import remoteConfig from '@react-native-firebase/remote-config';

const fetchConfig = async () => {
  try {
    await remoteConfig().setDefaults({
      feature_flag: false,
      api_endpoint: 'https://api.example.com'
    });
    await remoteConfig().fetch();
    const config = remoteConfig().getAll();
    return config;
  } catch (error) {
    console.error('Failed to fetch config:', error);
  }
};

Was this article helpful?