Affected: React Native SDK
Overview
In monolithic applications with multiple micro-frontends, managing feature flags can pose challenges. This article explores how you can simplify this complexity using the LaunchDarkly React Native SDK, tailored to your current setup.
Solution
Each pattern below addresses a different facet of the multi‑environment challenge. You can adopt either pattern on its own or combine them when both apply.
1. One LD client per project, backed by a hash table
The LaunchDarkly React Native SDK supports one active client per mobile key. When you need to work with multiple environments in one bundle, you can create a separate client for each environment, then expose them through a helper.
Example: Custom Hook
// ldClients.ts (initialised at app start‑up)
import {
initialize,
LDClient,
LDContext,
LDConfig,
} from '@launchdarkly/react-native-client-sdk';
export type EnvKey = 'dev' | 'staging' | 'production';
const envMobileKeys: Record<EnvKey, string> = {
dev: 'mobile-123-dev',
staging: 'mobile-456-stg',
production: 'mobile-789-prod',
};
const ldClients: Partial<Record<EnvKey, LDClient>> = {};
/**
* Create, cache, and return the client for the requested environment.
*/
export async function initLdClient(
env: EnvKey,
context: LDContext,
): Promise<LDClient> {
if (ldClients[env]) {
return ldClients[env] as LDClient;
}
const config: LDConfig = { pollInterval: 30, withReasons: true };
const client = await initialize(envMobileKeys[env], context, config);
ldClients[env] = client;
return client;
}
/**
* Retrieve a client that has already been initialised.
*/
export function getLdClient(env: EnvKey): LDClient {
const client = ldClients[env];
if (!client) {
throw new Error(`LD client for ${env} has not been initialised`);
}
return client;
}Example: Using a client inside a micro‑frontend
// FeatureToggle.tsx
import { useEffect, useState } from 'react';
import { getLdClient } from '../ldClients';
export function FeatureToggle() {
const client = getLdClient('staging'); // this micro‑frontend points at staging
const [enabled, setEnabled] = useState(false);
useEffect(() => {
// initial value
setEnabled(client.boolVariation('my-flag', false));
// live updates
const handler = (_ctx: LDContext, keys: string[]) => {
if (keys.includes('my-flag')) {
setEnabled(client.boolVariation('my-flag', false));
}
};
client.on('change', handler);
return () => client.off('change', handler);
}, [client]);
return enabled ? <NewExperience /> : <OldExperience />;
}2. Use multi‑context for richer targeting
When you need to consider several dimensions, for example, user, device, and tenancy, package them with the LaunchDarkly multi-context feature.
Example: Multi-context feature
import { getLdClient } from './ldClients';
import { LDContext } from '@launchdarkly/react-native-client-sdk';
async function identifyAndFetch() {
const client = getLdClient('production');
const ctx: LDContext = {
kind: 'multi',
user: { key: 'user-123', plan: 'premium' },
device: { key: 'device-abc', platform: 'ios' },
};
await client.identify(ctx);
const variant = client.stringVariation('new-checkout', 'control');
// …
}