⚠️ Demonstration mock — react-native-encore-mock is not the real Encore SDK and will be deleted after the demo.
Mock vs Live Mode

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:

src/lib/encore.js
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 AcceptonPurchaseRequest → your billing → completePurchaseRequest → resolves status: 'granted'.
  • A sponsored offer’s partner card → resolves status: 'completed' directly (no billing — the brand sponsors it). See Sponsored Offers.
  • DismissonPassthrough → resolves status: 'dismissed'.
  • Logs every call to the console ([encore:mock] …), respecting logLevel.

Built-in offers (DEFAULT_OFFERS, override via createMockEncore({ offers })):

PlacementTypeOffer
cancellation_flowsponsoredBrand-sponsored partner carousel — Disney+, Netflix, Spotify…
feature_paywallretention7-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:

metro.config.js
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:

  1. 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
  2. Set your key and flip the switch:
    export const ENCORE_API_KEY = 'pk_live_…';
    export const USE_MOCK = false;
  3. 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_KEY from an env file (e.g. react-native-config). See the FAQ.