Skip to content

Migration Guide: v10.x to v11.0.0+#

This guide will help you migrate from Storyteller SDK v10.x (Old Architecture) to v11.0.0+ (New Architecture).

The callback examples below are checked against v10.8.2. This guide covers the architecture and API transition into v11; installing v12 also requires the v11-to-v12 host migration.

Overview of Changes#

Major Changes#

  1. React Native New Architecture: v11.0.0+ requires the New Architecture to be enabled
  2. API Style: Changed from callbacks to Promises
  3. Import Changes: Module exports have been reorganized
  4. TypeScript: Enhanced type definitions and better TypeScript support

Step-by-Step Migration#

Step 1: Update SDK Version#

# Select the v11 release line for this migration
npm install @getstoryteller/react-native-storyteller-sdk@^11.0.0

# Or with yarn
yarn add @getstoryteller/react-native-storyteller-sdk@^11.0.0

Step 2: Enable New Architecture#

Android#

Update android/gradle.properties:

- newArchEnabled=false
+ newArchEnabled=true

iOS#

Update ios/Podfile:

- ENV['RCT_NEW_ARCH_ENABLED'] = '0'
+ ENV['RCT_NEW_ARCH_ENABLED'] = '1'

Make sure the Storyteller CocoaPods sources are present at the top of the file:

source 'https://cdn.cocoapods.org/'
source 'https://github.com/getstoryteller/storyteller-lottie-ios-podspec.git'
source 'https://github.com/getstoryteller/storyteller-sdk-ios-podspec.git'

Step 3: Clean and Rebuild#

# Clean everything
cd android && ./gradlew clean
cd ../ios && pod deintegrate

# Reinstall dependencies
cd ..
rm -rf node_modules
npm install # or yarn

# Reinstall iOS pods
cd ios && pod install

# Clear Metro cache
npx react-native start --reset-cache

Step 4: Update Initialization Code#

import StorytellerSdk from '@getstoryteller/react-native-storyteller-sdk';

try {
  await StorytellerSdk.initialize('YOUR_API_KEY', 'USER_ID');
  console.log('Initialized');
} catch (error) {
  console.error('Initialization failed:', error);
}
import Storyteller from '@getstoryteller/react-native-storyteller-sdk';

Storyteller.initialize(
  {
    apiKey: 'YOUR_API_KEY',
    externalId: 'USER_ID',
  },
  (callback) => {
    if (callback.result) {
      console.log('Initialized');
    }
  }
);

Step 5: Update Components Implementation#

Some examples are provided below. Check individual component documentation for more details.

import {
  CellType,
  StorytellerStoriesRowView,
  type DataLoadCompletedEvent,
} from '@getstoryteller/react-native-storyteller-sdk';

// Use this excerpt in a component that owns rowRef and customTheme.
<StorytellerStoriesRowView
  ref={rowRef}
  style={{ height: 100 }}
  configuration={{
    categories: ['category-id'],
    cellType: CellType.round,
    theme: customTheme,
  }}
  onDataLoadCompleted={(event: DataLoadCompletedEvent) => {
    console.log('Loaded:', event);
    if (event.success) {
      console.log(`Loaded ${event.dataCount} stories`);
    } else {
      console.error('Error loading data:', event.error);
    }
  }}
  onDataLoadStarted={() => {
    console.log('Started');
  }}
  onPlayerDismissed={() => {
    console.log('Dismissed');
  }}
/>
<StorytellerStoriesRowView
  ref={rowRef}
  style={{ height: 100 }}
  configuration={{
    categories: ['category-id'],
    cellType: 'round',
    theme: customTheme,
  }}
  onDataLoadCompleted={(isSuccessful, error, dataCount) => {
    console.log('Loaded:', isSuccessful, dataCount);
  }}
  onDataLoadStarted={() => {
    console.log('Started');
  }}
  onPlayerDismissed={() => {
    console.log('Dismissed');
  }}
/>

Step 6: Update Storyteller Method Calls#

Some examples are provided below. Check individual methods documentation for more details.

await StorytellerSdk.openStory('story-id');
Storyteller.openStory('story-id', (error) => {
  console.error('Unable to open Story:', error);
});

Custom Attributes#

StorytellerSdk.setCustomAttribute('key', 'value');
const attributes = await StorytellerSdk.customAttributes();
console.log(attributes);
Storyteller.setCustomAttribute('key', 'value');
Storyteller.customAttributes((attributes) => {
  console.log(attributes);
});
if (StorytellerSdk.isStorytellerDeeplink(url)) {
  await StorytellerSdk.openDeeplink(url);
}
Storyteller.isStorytellerDeeplink(url, ({ result: isStorytellerLink }) => {
  if (isStorytellerLink) {
    Storyteller.openDeeplink(url, (response: unknown) => {
      if (typeof response === 'object' && response !== null && 'result' in response) {
        if (response.result === true) console.log('Opened on iOS');
        else console.warn('Deep-link open failed', response.result);
      }
    });
  }
});

In the checked v10.8.2 package, isStorytellerDeeplink calls back with { result: boolean }. openDeeplink has a historical typing mismatch: iOS sends { result: boolean }, while Android calls back only on error with { result: string }. The sample treats the response as unknown and checks it at runtime. A truthy callback object does not mean success, and Android does not provide a success callback. v11 uses the Promise-based API above.

Support#