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);
}
};