Mock vs Live Mode
react-native-encore-mock implements Encore’s entire surface in memory and drives
the real callback flow — so your code is identical whether you’re on the mock or the
real native SDK.
The switch
One constant in your app controls everything, consumed in exactly one place:
import { createMockEncore } from 'react-native-encore-mock';
// import realEncore from '@tryencorekit/react-native';
import { USE_MOCK } from './encoreConfig';
const mockClient = createMockEncore({ offers: GAME_OFFERS });
const Encore = USE_MOCK ? mockClient : realEncore;
export default Encore;Because everything imports from this file, flipping USE_MOCK re-points the whole
app — no other code changes.
What the mock does
- Holds in-memory user, attributes, and registered callbacks.
placement(id).show()presents a styled<Modal>— a retention sheet or a sponsored partner carousel, depending on the offer type.- A retention offer’s Accept →
onPurchaseRequest→ your billing →completePurchaseRequest→ resolvesstatus: 'granted'. - A sponsored offer’s partner card → resolves
status: 'completed'directly (no billing — the brand sponsors it). See Sponsored Offers. - Dismiss →
onPassthrough→ resolvesstatus: 'dismissed'. - Logs every call to the console (
[encore:mock] …), respectinglogLevel.
Built-in offers (DEFAULT_OFFERS, override via createMockEncore({ offers })):
| Placement | Type | Offer |
|---|---|---|
cancellation_flow | sponsored | Brand-sponsored partner carousel — Disney+, Netflix, Spotify… |
feature_paywall | retention | 7-day free trial (paid) |
Bundling with zero native dependencies
If your encore.js imports the real @tryencorekit/react-native in a dormant
branch, Metro still needs to resolve that import even in mock mode (where the package
isn’t installed). Alias it to a tiny stub so the bundle stays native-free:
let realInstalled = true;
try { require.resolve('@tryencorekit/react-native'); } catch { realInstalled = false; }
config.resolver.resolveRequest = (ctx, name, platform) => {
if (!realInstalled && name === '@tryencorekit/react-native') {
return { type: 'sourceFile', filePath: path.resolve(__dirname, 'src/lib/encoreSdkStub.js') };
}
return ctx.resolveRequest(ctx, name, platform);
};Once you npm install @tryencorekit/react-native, require.resolve succeeds and the
alias steps aside automatically — no config edit needed.
Going live — exactly what to do
When a real pk_ key arrives:
- Install the native SDK and rebuild the native app / dev client:
npm install @tryencorekit/react-native cd ios && pod install && cd .. # bare RN # or: npx expo prebuild && npx expo run:ios # Expo dev build - Set your key and flip the switch:
export const ENCORE_API_KEY = 'pk_live_…'; export const USE_MOCK = false; - Rebuild. The real SDK renders offers (including the sponsored partner carousel) natively; the mock is simply unused.
No call-site changes — placement().show(), isGranted(result), and your callbacks
are identical. TypeScript users get types from the real package automatically (no
shim to manage — react-native-encore-mock already shipped its own types in mock mode).
Prefer not to hard-code the key? Source
ENCORE_API_KEYfrom an env file (e.g.react-native-config). See the FAQ.