> ## Documentation Index
> Fetch the complete documentation index at: https://launchdarkly-preview.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# React Native SDK 6.x to 7.0 migration guide

> This topic explains the changes in the React Native SDK 7 release and how to migrate to that version.

> For the complete documentation index, see [llms.txt](/llms.txt). For the full documentation snapshot, see [llms-full.txt](/llms-full.txt).

## Overview

This topic explains the changes in the React Native SDK 7.0 release and how to adapt code that uses a 6.x version of the [React Native SDK](/sdk/client-side/react/react-native) to use version 7.0 or later.

Before you migrate to version 7.0, update to the latest 6.x version. Some of the changes that are mandatory in 7.0 were originally added in a 6.x version and made optional.

If you update to the latest 6.x version, deprecation warnings appear in areas of your code that need to be changed for 7.

0. You can update them at your own pace while still using 6.x, rather than migrating everything simultaneously. To learn more about updating to the latest 6.x version, visit the [SDK's GitHub repository](https://github.com/launchdarkly/react-native-client-sdk).

## Identifying supported React Native versions for the 7.0 SDK

The minimum React Native version for LaunchDarkly 7.0 SDK is 0.69.

LaunchDarkly no longer supports earlier React Native versions, as stated in the [End of Life policy](https://launchdarkly.com/policies/end-of-life-policy/).

## Understanding contexts

Many LaunchDarkly customers create targeting rules for feature flags based on a variety of different information, including attributes pertaining to users, organizations, devices, and more. In previous versions of the LaunchDarkly SDK, you could define this information in a user object, using a combination of built-in and custom attributes. Now you can define this information in a more structured way, using **contexts**.

Each context has a required attribute called `kind` that you can use to categorize context instances for targeting and Experimentation. You can also add other attributes. Attributes can be strings, booleans, numbers, arrays, or JSON objects.

When you evaluate a feature flag within your application, the flag's targeting rules use information from one or more kinds of contexts. For example, you may know:

* the username, first name, last name, and email address of a person, as part of a context with `kind` of "user"
* the company, department, and location of an organization, as part of a context with `kind` of "organization"
* the device, model, and operating system of an environment, as part of a context with `kind` of "device"

This new version of the LaunchDarkly SDK requires you to evaluate feature flags using an **evaluation context**, which is an object containing one or more contexts.

To learn more about contexts, read [Contexts](/home/flags/contexts).

## Migrating from users to contexts

The 7.0 version of this SDK lets you use contexts. When you migrate from version 6.x, you should replace every instance of a user with a context. Any instances of user you do not replace will continue to work to help migrating to contexts. However this support for LDUser is temporary and will be removed in a future version. We strongly recommend you replace all instances of user with context.

<Note
  title="LaunchDarkly assumes older versions of the SDK use <code>

user</code> contexts"
>
  A context always has a `kind` attribute. When older versions of the React Native SDK send events to LaunchDarkly, LaunchDarkly will convert the users in those events to contexts with a `kind` of `user`.

  If a flag configuration specifies any context `kind`s other than `user`, older versions of the React Native SDK will not evaluate the flag correctly. You must upgrade your SDK if you are going to use context `kind`s other than `user` in your flag configurations.
</Note>

The primary differences between working with users and working with contexts include the following:

* [Create contexts, not users](#understanding-differences-between-users-and-contexts): Where you previously created users, now you can create contexts.
* [Changes to attributes](#understanding-changes-to-built-in-and-custom-attributes): There are now fewer built-in attributes. You can still add as many custom attributes as you like, although the format has changed slightly. A flag's targeting rules can now address fields within a JSON object.
* [Changes to private attributes](#understanding-changes-to-private-attributes): You can mark specific attributes of a context as private, either across all contexts of any kind, or within a particular context or context kind.
* [Changes to anonymous users](#understanding-changes-to-anonymous-users): Client-side SDKs no longer automatically populate the device ID.
* [Changes to alias events](#understanding-changes-to-alias-events): The alias method has been removed.

### Understanding differences between users and contexts

Where you previously created users, now you can create contexts.

Here's how to construct a basic context, as compared with constructing a user:

<CodeGroup>
  ```js title="6.x syntax, user with key" theme={null}
      const user = {
        key: 'example-user-key'
      };

      const ldClient = new LDClient();
      const config = {
        mobileKey: 'example-mobile-key'
      };

      try {
        await ldClient.configure(config, user);
      } catch (err) {
        console.error(err);
      }
  ```

  ```js title="7.0 syntax, context with key" theme={null}
      const context = {
        kind: 'user',
        key: 'example-user-key'
      };

      const ldClient = new LDClient();
      const config = {
        mobileKey: 'example-mobile-key'
      };

      try {
        await ldClient.configure(config, context);
      } catch (err) {
        console.error(err);
      }
  ```
</CodeGroup>

<Warning
  title="Omitting the <code>

kind</code> creates a user object, not a context"
>
  If you omit the `kind` attribute when you create a context, then LaunchDarkly will assume the context kind is "user" when evaluating flags. Additionally, the SDK will assume you are working with a user object, rather than a context.

  Overall, this should make your upgrade easier, because your existing code will continue to work, as long as you don't make changes to your flag configuration or [bucket users based on the "secondary" attribute](#removing-the-secondary-attribute).

  However, if you are using version 7.0 of the SDK and you are omitting the `kind` attribute, then the following caveats apply:

  <ul><li> The fields in your user object must be <code>LDUser</code> fields, not <code>LDContext</code> fields. For example, to mark an attribute as private, you must use <code>privateAttributeNames</code> in the user object, not <code>\_meta.privateAttributes</code> as you would for a context object. To learn more, read [Understanding changes to private attributes](#understanding-changes-to-private-attributes) . </li> <li> Any additional attributes in your user object need to be inside the <code>custom</code> property of the <code>LDUser</code> , not at the top-level as they would in a context object. To learn more, read [Working with built-in and custom attributes](#working-with-built-in-and-custom-attributes) . </li></ul>

  We strongly recommend upgrading your SDK to take advantage of the context functionality.
</Warning>

Here's how to construct a basic context, with a context kind of something other than "user":

<CodeGroup>
  ```js title="7.0 syntax, single context with key" theme={null}
      const context = {
        kind: 'organization',
        key: 'example-organization-key'
      };

      await ldClient.configure(config, context);
  ```
</CodeGroup>

Here's how to construct a multi-context, which includes multiple context kinds:

<CodeGroup>
  ```js title="7.0 syntax, multi-context" theme={null}
      const deviceContext = {
        kind: 'device',
        type: 'iPad',
        key: 'example-device-key'
      }

      const userContext = {
        kind: 'user',
        key: 'example-user-key',
        name: 'Sandy',
        role: 'doctor'
      }

      const multiContext = {
        kind: 'multi',
        user: userContext,
        device: deviceContext
      }

      await ldClient.configure(config, multiContext);
  ```
</CodeGroup>

### Understanding changes to built-in and custom attributes

This section describes the changes to built-in and custom attributes in the 7.0 version of the SDK.

#### Working with built-in and custom attributes

In previous SDK versions, the user object included several built-in attributes for describing the user. It also included optional custom attributes, which you could add to a `custom` object within the user object and then populate.

In version 7.0, the only built-in attributes are `kind`, `key`, `name`, and `anonymous`. `Kind`, `key`, and `name` are strings, and `anonymous` is a boolean.

You can define additional attributes for a context by passing in a name and value for each. Additional attributes can be any JSON type, including boolean, number, string, array, or object. In version 7.0, you do not need to add custom attributes within a `custom` object.

Here's how to construct a context with additional attributes, as compared with constructing a similar user:

<CodeGroup>
  ```js title="6.x syntax, user with attributes" theme={null}
      const user = {
        key: 'example-user-key',
        firstName: 'Sandy',
        lastName: 'Smith',
        email: 'sandy@example.com'
        custom: {'groups': 'Global Health Services'}
      };
  ```

  ```js title="7.0 syntax, context with attributes" theme={null}
      const context = {
        kind: 'user',
        key: 'example-user-key',
        firstName: 'Sandy',
        lastName: 'Smith',
        email: 'sandy@example.com',
        groups: 'Global Health Services'
      };
  ```
</CodeGroup>

#### Referencing properties of an attribute object

In previous versions of the SDK, if you set the value of a user's custom attribute to an object, you could not reference that object in evaluations. In version 7.0, if a context attribute's value is a JSON object, you can reference properties of that object as the attribute in the targeting rules for a flag or segment.

Here's how to add object attributes to a context:

<CodeGroup>
  ```js title="7.0 syntax, context with object attributes" theme={null}
      const context = {
        kind: 'user',
        key: 'example-user-key',
        firstName: 'Sandy',
        lastName: 'Smith',
        email: 'sandy@example.com',
        address: {
          street: '123 Main St',
          city: 'Springfield'
        }
      };
  ```
</CodeGroup>

In your flag or segment targeting, use `/` as the delimiter to refer to specific object fields. For example, you can use `/address/city` in your targeting. To learn more, read [Target with flags](/home/flags/target).

#### Removing the secondary attribute

In previous versions of the SDK, you could set the value of a user's `secondary` attribute, as an optional secondary key for a user. The SDK would incorporate this attribute into the variation bucket assignment hash.

In version 7.0, the `secondary` attribute has been removed. If you were previously using this attribute as part of distinguishing [percentage rollouts](/home/releases/percentage-rollouts#percentage-rollout-logic), that will no longer work for your users.

### Understanding changes to private attributes

As in previous versions of the SDK, you can mark specific attributes of a context as private. This restricts the context data your application sends to LaunchDarkly, while still using that data for flag targeting.

In version 7.0, there are two scopes for which you can mark attributes as private:

* Across all contexts of any context kind. You might use this if you want to ensure that the SDK never stores an "email" attribute in LaunchDarkly, no matter whether it occurs in a user context, an organization context, or something else.
* Within a particular context or context kind. You might use this if you want an "email" attribute to be private in a user context, but not in an organization context.

In the first example, all attributes are marked private for all contexts. In the second example, the "email" and "address" attributes are private for all contexts:

<CodeGroup>
  ```js title="7.0 syntax, all attributes marked private" theme={null}
      const config = {
        mobileKey: 'example-mobile-key',
        allAttributesPrivate: true
      };

      await ldClient.configure(config, context);
  ```

  ```js title="7.0 syntax, two attributes marked private" theme={null}
      const config = {
        mobileKey: 'example-mobile-key',
        privateAttributes: ['email', 'address']
      };

      await ldClient.configure(config, context);
  ```
</CodeGroup>

To learn more, read `allAttributesPrivate` and `privateAttributes` on [`LDConfig`](https://launchdarkly.github.io/react-native-client-sdk/index.html#LDConfig).

Here's how to mark an attribute as private for a particular context:

<CodeGroup>
  ```js title="7.0 syntax, attribute marked private for one context" theme={null}
      const context = {
        kind: 'user',
        key: 'example-user-key',
        firstName: 'Sandy',
        lastName: 'Smith',
        email: 'sandy@example.com',
        address: {
          street: '123 Main St',
          city: 'Springfield'
        },
        _meta: {
          privateAttributes: ['email', '/address/street']
        }
      };
  ```
</CodeGroup>

For attributes that are objects, you can mark specific fields private, using the `/` delimiter followed by the attribute name, then the `/` delimiter followed by the JSON property within the value.

For example, for the attribute `"address": { "street": "Main St", "city": "Springfield" }`, you could set just the `/address/street` as private.

The `privateAttributeNames` attribute that existed in a user object in version 6.x has been renamed to `privateAttributes` in version 7.

0. It has moved from the top level of a user object into the `_meta` object within a context. To learn more, read [`privateAttributes`](https://launchdarkly.github.io/js-sdk-common/interfaces/LDContextMeta.html#privateAttributes).

### Understanding changes to anonymous users

In 6.x versions of the SDK, the user key is mandatory when building an anonymous user because the underlying Android SDK mandates it.

In the 7.0 version of the SDK, you can omit the context key when building an anonymous context, and the SDK sets the context key to a generated UUID. If you omit the context key and do not mark the context as anonymous, the SDK gives a usage error.

If you are working with a multi-context, you can mark some contexts anonymous and not others. Here's an example:

<CodeGroup>
  ```js title="7.0 syntax, working with anonymous contexts" theme={null}
      // This user context is not anonymous
      const userContext = {
        kind: 'user',
        key: 'example-user-key'
      }

      // This device context is anonymous
      // The key is omitted, and the SDK will automatically generate one
      const deviceContext = {
        kind: 'device',
        deviceId: '12345',
        anonymous: true
      }

      // The multi-context contains one anonymous context
      // and one non-anonymous context
      const multiContext = {
        kind: 'multi',
        user: userContext,
        device: deviceContext
      }
  ```
</CodeGroup>

### Understanding changes to alias events

In previous versions of the SDK, multiple user objects could represent one person. For example, this could happen the first time a person logged in to your application. The person might be represented by an anonymous user before they logged in, and a different user after they logged in. You could associate these two LaunchDarkly users by sending an `alias` event in the SDK.

With the introduction of contexts, the person in this scenario is represented by two different context kinds. For example, before they log in, they might be represented by a device context. After they log in, they might be represented by a multi-context, for example, by one context kind based on their device and simultaneously by another context kind based on their user information.

The 7.0 version of the SDK removes the ability to send an `alias` event. If you currently [alias users](/sdk/features/aliasing-users), you will need to remove this code when you migrate to version 7.0.

If you want to continue associating two contexts with each other, you can use two different context kinds, and then identify a multi-context that includes both individual contexts when you want the association to occur. Unlike the aliasing method, the association doesn't persist between calls. You must send the contexts you want to associate in each `variation` or `identify` call and each `track` call.

Here's how:

<CodeGroup>
  ```js title="3.0 syntax, identifying a multi-context" theme={null}
      const deviceContext = {
        kind: 'device',
        key: 'example-device-key',
        type: 'iPad'
      }

      const userContext = {
        kind: 'user',
        key: 'example-user-key',
        name: 'Sandy',
        role: 'doctor'
      }

      const multiContext = {
        kind: 'multi',
        user: userContext,
        device: deviceContext
      }

      try {
        await client.identify(multiContext);
        console.log("Multi-context's flags available");
      } catch (err) {
        console.error(err);
      }
  ```
</CodeGroup>

To learn more, read [`identify`](https://launchdarkly.github.io/react-native-client-sdk/classes/LDClient.html#identify).

## Understanding changes to configuration options

In the 7.0 version of the SDK, several configuration options have changed:

* The `allAttributesPrivate` and `privateAttributes` configuration options both now apply to all contexts of any context kind. To learn more, read [Understanding changes to private attributes](#understanding-changes-to-private-attributes).
* `allUserAttributesPrivate`, `privateAttributeNames` are now called `allAttributesPrivate` and `privateAttributes`. To learn more, read [Understanding changes to private attributes](#understanding-changes-to-private-attributes).
* `pollUri`, `streamUri`, `eventsUri` are now called `pollUrl`, `streamUrl` and `eventsUrl`.
* `eventsCapacity` is now called `eventCapacity`
* `eventsFlushIntervalMillis`, `connectionTimeoutMillis`, `pollingIntervalMillis`, `backgroundPollingIntervalMillis` are now called `flushInterval`, `connectionTimeout`, `pollingInterval`, `backgroundPollingInterval`.
* `diagnosticRecordingIntervalMillis` is now called `diagnosticRecordingInterval`
* `maxCachedUsers` is now called `maxCachedContexts`
* The `autoAliasingOptOut` option has been removed.
* The `inlineUsersInEvents` option has been removed.

To learn more, read [LDConfig](https://launchdarkly.github.io/react-native-client-sdk/index.html#LDConfig).

## Understanding what was deprecated

All types and methods that were marked as deprecated in the last 6.x release have been removed from the 7.0 release. If you were using these with a recent version previously, you should already have received deprecation warnings at compile time, with suggestions about their recommended replacements.

For a full list of deprecated types and methods, read the [release notes in Github](https://github.com/launchdarkly/react-native-client-sdk/releases).
