---
title: "Миграция Adapty React Native SDK на v. 4.0"
description: "Перейдите на Adapty React Native SDK v4.0 (beta): замените paywall API на flow API, совместимые как с Flow Builder, так и с Paywall Builder."
---

Adapty React Native SDK 4.0 (beta) вводит флоу и переименовывает paywall API соответствующим образом. Новые API работают как с новым Flow Builder, так и с существующим Paywall Builder — никаких изменений в настройках дашборда Adapty не требуется.
## Краткий справочник \{#quick-reference\}
| v3 | v4 |
|---|---|
| `adapty.getPaywall(placementId, locale?, params?)` | `adapty.getFlow(placementId, params?)` |
| `adapty.getPaywallForDefaultAudience(placementId, locale?, params?)` | `adapty.getFlowForDefaultAudience(placementId, params?)` |
| `adapty.getPaywallProducts(paywall)` | `adapty.getPaywallProducts(flow)` |
| `adapty.logShowPaywall(paywall)` | `adapty.logShowFlow(flow)` |
| `AdaptyPaywall` (тип) | `AdaptyFlow` |
| `createPaywallView(paywall)` | `createFlowView(flow)` |
| `AdaptyPaywallView` (компонент) | `AdaptyFlowView` |
| `EventHandlers` (тип) | `FlowEventHandlers` |
| `onPaywallShown` | `onAppeared` |
| `onPaywallClosed` | `onDisappeared` |
| `onRenderingFailed` | `onError` |
`AdaptyPaywallProduct` сохраняет своё название — продукты по-прежнему принадлежат флоу, а `getPaywallProducts` теперь принимает `AdaptyFlow`. Методы `getFlow` и `getFlowForDefaultAudience` больше не принимают параметр `locale`. Методы представления `present`, `dismiss`, `setEventHandlers` и `showDialog`, а также обработчики событий `onCloseButtonPress`, `onUrlPress`, `onCustomAction`, `onProductSelected`, `onPurchaseStarted`, `onPurchaseCompleted`, `onPurchaseFailed`, `onRestoreStarted`, `onRestoreCompleted`, `onRestoreFailed`, `onLoadingProductsFailed`, `onWebPaymentNavigationFinished` и `onAndroidSystemBack` сохраняют те же имена, что и в v3. Некоторые поведения по умолчанию изменились — см. [Изменения поведения по умолчанию](#default-behavior-changes).
## Минимальная версия iOS \{#minimum-ios-version\}

Adapty React Native SDK 4.0 повышает минимальную версию iOS с 13.0 до **iOS 15.0**. Перед обновлением установите значение deployment target не ниже 15.0.
## Установка \{#installation\}
### Обновите пакет \{#update-the-package\}

v4.0 — это предварительный релиз, поэтому укажите точную версию — npm не выбирает предварительные версии через диапазоны с `^` или `~`:

```bash showLineNumbers
npm install react-native-adapty@4.0.0-beta.1
# or
yarn add react-native-adapty@4.0.0-beta.1
```
### iOS: нативные SDK теперь поставляются через Swift Package Manager

[Репозиторий спецификаций CocoaPods переходит в режим только для чтения в декабре 2026 года](https://blog.cocoapods.org/CocoaPods-Specs-Repo/), поэтому начиная с v4 нативные SDK `Adapty`, `AdaptyUI` и `AdaptyPlugin` **больше не подключаются как под-зависимости CocoaPods** — podspec получает их через **Swift Package Manager** (с помощью хелпера `spm_dependency`). Это требует двух вещей:
- **React Native 0.75 или выше** — необходим хелпер подспеки `spm_dependency`. На более старой версии `pod install` завершается с явной ошибкой; сначала обновите React Native или оставайтесь на `react-native-adapty` 3.x.
- **Динамические фреймворки** — зависимости SPM требуют динамической линковки. Способ её включения отличается для Expo и bare React Native.

#### Expo

Добавьте конфиг-плагин [`expo-build-properties`](https://docs.expo.dev/versions/latest/sdk/build-properties/) и установите для iOS-фреймворков динамическую линковку в `app.json` (или `app.config.js`):
```json showLineNumbers title="app.json"
{
  "expo": {
    "plugins": [
      [
        "expo-build-properties",
        {
          "ios": {
            "useFrameworks": "dynamic"
          }
        }
      ]
    ]
  }
}
```

Затем установите плагин и пересоздайте нативный проект:

```bash showLineNumbers
npx expo install expo-build-properties
npx expo prebuild --clean
```

#### Bare React Native

Добавьте динамические фреймворки в ваш iOS-таргет, затем переустановите pods:

```ruby showLineNumbers title="ios/Podfile"
use_frameworks! :linkage => :dynamic
```
```bash showLineNumbers
cd ios && pod install --repo-update
```

Если ранее вы подключали `Adapty`, `AdaptyUI` или `AdaptyPlugin` как зависимости CocoaPods, сначала удалите все явные строки `pod 'Adapty'`, `pod 'AdaptyUI'` или `pod 'AdaptyPlugin'` из вашего `Podfile`.
:::warning
Переход со статической компоновки по умолчанию на динамические фреймворки может конфликтовать с библиотеками, которые ещё не поддерживают модульные заголовки, а также несовместим с Flipper. Если возникнут ошибки сборки, обратитесь к этой [статье об интеграции Swift Package Manager с библиотеками React Native](https://www.callstack.com/blog/integrating-swift-package-manager-with-react-native-libraries).
:::

См. раздел [Установка Adapty SDK](sdk-installation-reactnative) для полной инструкции по настройке.
## Получение флоу \{#fetching-flows\}
### getPaywall → getFlow

Возвращаемый тип меняется с `AdaptyPaywall` на `AdaptyFlow`, а параметр `locale` убирается — при рендеринге флоу локаль определяется автоматически; для кастомных пейволов все локали возвращаются в `flow.remoteConfigs`:

```diff showLineNumbers
- const paywall = await adapty.getPaywall('YOUR_PLACEMENT_ID', 'en');
+ const flow = await adapty.getFlow('YOUR_PLACEMENT_ID');
```

`getPaywallForDefaultAudience` переименовывается аналогично:
```diff showLineNumbers
- const paywall = await adapty.getPaywallForDefaultAudience('YOUR_PLACEMENT_ID', 'en');
+ const flow = await adapty.getFlowForDefaultAudience('YOUR_PLACEMENT_ID');
```

### getPaywallProducts(paywall) → getPaywallProducts(flow)

`getPaywallProducts` сохраняет своё название, но теперь принимает `AdaptyFlow`:

```diff showLineNumbers
- const products = await adapty.getPaywallProducts(paywall);
+ const products = await adapty.getPaywallProducts(flow);
```
## Модель данных \{#data-model\}

`getFlow` возвращает `AdaptyFlow` вместо `AdaptyPaywall`, и структура объекта изменилась:
| Поле v3 `AdaptyPaywall` | Поле v4 `AdaptyFlow` | Действие |
|---|---|---|
| `remoteConfig?` (одно) | `remoteConfigs?: AdaptyRemoteConfig[]` (массив) | Флоу содержит по одному Remote Config на каждый настроенный язык. Читайте тот, который соответствует пользователю: `flow.remoteConfigs?.find((c) => c.lang === 'en')`. |
| `products` | `flow.paywalls[i].productIdentifiers` | Идентификаторы продуктов теперь хранятся в каждом варианте флоу, а не в самом флоу. |
| `webPurchaseUrl?` | `flow.paywalls[i].webPurchaseUrl` | Перемещено из флоу в каждый вариант пейвола. |
| `version?: number` | `flowVersionId?: string` | Переименовано, тип изменён с `number` на `string`. |
| `hasViewConfiguration` | удалено | Удалите все проверки `hasViewConfiguration` из своего кода. |
| `requestLocale` | удалено | Локаль больше не является частью модели. |
| _(новое)_ | `paywalls: AdaptyFlowPaywall[]` | Каждый элемент — это один вариант пейвола во флоу. |
| _(новое)_ | `responseCreatedAt: number` | Временная метка ответа сервера в миллисекундах. |
Product identifiers moved from the flow to each variation:

```diff showLineNumbers
- const ids = paywall.products;
+ const ids = flow.paywalls[0].productIdentifiers;
```
## Методы веб-пейвола \{#web-paywall-methods\}

`openWebPaywall` и `createWebPaywallUrl` сохраняют свои названия, но первым аргументом теперь передаётся `AdaptyFlowPaywall` (вариант флоу) вместо `AdaptyPaywall`. По-прежнему можно передать `AdaptyPaywallProduct`.

```diff showLineNumbers
  const flow = await adapty.getFlow('YOUR_PLACEMENT_ID');
- await adapty.openWebPaywall(paywall);
+ await adapty.openWebPaywall(flow.paywalls[0]);
```
## Отслеживание просмотров флоу \{#tracking-flow-views\}
### logShowPaywall → logShowFlow

`logShowPaywall` переименован в `logShowFlow` и теперь принимает `AdaptyFlow`. Событие по-прежнему логируется для той же вариации, так что существующие метрики воронки и A/B-тестов продолжат работать без изменений в дашборде.

```diff showLineNumbers
- await adapty.logShowPaywall(paywall);
+ await adapty.logShowFlow(flow);
```

Как и в v3, вызывать этот метод при отображении флоу или пейволов, отрисованных с помощью [Flow Builder](adapty-flow-builder) или [Paywall Builder](adapty-paywall-builder), не нужно — Adapty отслеживает такие просмотры автоматически.
## Отображение флоу \{#displaying-flows\}
### createPaywallView → createFlowView

Переименуйте фабричную функцию и передайте `AdaptyFlow`. Методы возвращаемого контроллера (`present`, `dismiss`, `setEventHandlers`, `showDialog`) остаются без изменений:

```diff showLineNumbers
- import { createPaywallView } from 'react-native-adapty';
+ import { createFlowView } from 'react-native-adapty';

- const view = await createPaywallView(paywall);
+ const view = await createFlowView(flow);
  await view.present();
```
### AdaptyPaywallView → AdaptyFlowView

Если вы используете React-компонент для рендеринга, переименуйте его и передайте проп `flow`:

```diff showLineNumbers
- import { AdaptyPaywallView } from 'react-native-adapty';
+ import { AdaptyFlowView } from 'react-native-adapty';

- <AdaptyPaywallView paywall={paywall} /* … */ />
+ <AdaptyFlowView flow={flow} /* … */ />
```
:::note
Представление флоу, созданное с помощью `createFlowView`, одноразовое: после вызова `dismiss()` оно уничтожается, поэтому для повторного показа флоу вызовите `createFlowView` снова. Встроенный `AdaptyFlowView` закрывается путём размонтирования — возврат `true` из обработчика не закрывает встроенное представление, поэтому вместо этого изменяйте собственное состояние, например в `onCloseButtonPress`.
:::
## Обработка событий \{#handling-events\}

Интерфейс обработчика событий переименован с `EventHandlers` на `FlowEventHandlers`, а три колбэка также переименованы. Тела существующих обработчиков менять не нужно — просто переименуйте:

```diff showLineNumbers
- onPaywallShown: () => { /* … */ },
+ onAppeared: () => { /* … */ },

- onPaywallClosed: () => { /* … */ },
+ onDisappeared: () => { /* … */ },

- onRenderingFailed: (error) => { /* … */ },
+ onError: (error) => { /* … */ },
```
Все остальные обработчики событий сохраняют свои имена. Два из них также получают второй аргумент: `onPurchaseCompleted` теперь принимает `(purchaseResult, product)`, а `onPurchaseFailed` — `(error, product)`, где `product` — это участвующий в операции `AdaptyPaywallProduct`. Полный список см. в разделе [Обработка событий флоу и пейвола](react-native-handling-events-1).

:::note
`onDisappeared` срабатывает только для флоу, представленного модально через `createFlowView().present()`. Компонент `AdaptyFlowView` не предоставляет его как проп — чтобы скрыть встроенное представление, размонтируйте его.
:::

В v4 также появился ряд возможностей, которые можно подключить по желанию:
- Методы `adapty.openWebUrl(url, openIn?)` и `adapty.requestAppReview()` — они обеспечивают работу обработчиков `onUrlPress` и `onRequestAppReview` по умолчанию, так что URL и запросы на отзыв об приложении обрабатываются нативно прямо из коробки. Вызывайте их напрямую только если переопределяете эти обработчики.
- Обработка покупок в режиме наблюдателя внутри флоу через новые обработчики `onObserverPurchaseInitiated` / `onObserverRestoreInitiated`. См. [Обработка покупок в режиме наблюдателя](react-native-handling-events-1#handle-purchases-in-observer-mode).
## Удалённые и устаревшие API \{#removed-and-deprecated-apis\}
### setFallbackPaywalls → setFallback

`setFallbackPaywalls` удалён. Используйте `setFallback` с тем же аргументом:

```diff showLineNumbers
- await adapty.setFallbackPaywalls(fileLocation);
+ await adapty.setFallback(fileLocation);
```
### Удалённые экспорты \{#removed-exports\}

Эти символы больше не экспортируются из `react-native-adapty`. Удалите их импорты:

- **`AdaptyPaywall`**: Используйте `AdaptyFlow` вместо него.
- **`ProductReference`**: Используйте `AdaptyProductIdentifier`, считываемый из `flow.paywalls[i].productIdentifiers`.
- **`AdaptyPaywallBuilder`**: Удалён. Флоу и пейволы рендерятся нативно.
- **`AdaptyAndroidSubscriptionUpdateParameters`**: Используйте вложенную форму `subscriptionUpdateParams` (см. ниже).
### activate: lockMethodsUntilReady

`lockMethodsUntilReady` удалён, и теперь это поведение включено постоянно. Удалите его из вызова `activate` — иначе код не скомпилируется:

```diff showLineNumbers
- await adapty.activate('PUBLIC_SDK_KEY', { lockMethodsUntilReady: true });
+ await adapty.activate('PUBLIC_SDK_KEY');
```
### Обновление подписки на Android с помощью makePurchase \{#makepurchase-android-subscription-update\}

Плоская структура параметров обновления подписки на Android удалена. Перенесите `oldSubVendorProductId` и `prorationMode` в вложенный объект `subscriptionUpdateParams`, а `isOfferPersonalized` оставьте на верхнем уровне. Полный пример см. в разделе [Совершение покупок](react-native-making-purchases).
### Android: отступы безопасной зоны \{#android-safe-area-paddings\}

Булевый ресурс Android `<bool name="adapty_paywall_enable_safe_area_paddings">…</bool>` удалён. Удалите его из `res/values/bools.xml` и управляйте отступами безопасной зоны во время выполнения через параметр `enableSafeArea` при создании представления флоу. По умолчанию он равен `true` для модального отображения и `false` для встроенного компонента.
### Режим мок-данных \{#mock-mode\}

Если вы запускаете SDK в режиме мок-данных (Expo Go или веб-превью), переименуйте ключ мок-конфигурации `paywalls` в `flows`.
## Изменения поведения по умолчанию \{#default-behavior-changes\}

Эти изменения не вызывают ошибок компиляции, поэтому проверяйте их во время выполнения:
- **`onAndroidSystemBack`**: Поведение по умолчанию изменилось: раньше нажатие закрывало вью, теперь — оставляет открытой. Чтобы вернуть прежнее поведение, возвращайте `true` из обработчика.
- **`onPurchaseCompleted`**: Поведение по умолчанию изменилось: раньше вью закрывалась (если пользователь не отменял покупку), теперь — всегда остаётся открытой. Чтобы вернуть прежнее поведение, возвращайте `purchaseResult.type !== 'user_cancelled'` из обработчика.
- **`onRestoreCompleted`**: Поведение по умолчанию изменилось: раньше вью закрывалась после успешного восстановления, теперь — остаётся открытой. Чтобы вернуть прежнее поведение, возвращайте `true` из обработчика.
- **`onUrlPress`**: По умолчанию URL теперь открывается через нативный слой с учётом настройки браузера (встроенного или внешнего) из дашборда. Переопределите обработчик, чтобы открывать URL самостоятельно.
## Устаревший API онбординга \{#onboarding-api-deprecation\}

Устаревший API онбординга помечен как deprecated в v4.0 в пользу [Flow Builder](adapty-flow-builder). Он продолжает работать, а IDE отмечает устаревшие символы через аннотации `@deprecated` — никаких предупреждений в рантайме нет. Эти символы будут удалены в будущих версиях, поэтому планируйте перенос ваших онбордингов во Flow Builder.

Устаревшие символы: `getOnboarding`, `getOnboardingForDefaultAudience`, `createOnboardingView` и `AdaptyOnboardingView`.