For the complete documentation index, see llms.txt. This page is also available as Markdown.

Redux SDK

Integrate Harness FME feature flags directly into your Redux state management for seamless feature delivery in web applications.

This guide provides detailed information about our Redux SDK. This library is built on top of our regular JavaScript SDK to ease the integration in applications using Redux by providing a reducer to manage the Split-related state, a set of actions that you can use to interact with the SDK, selectors to easily get Split-desired data, and helper functions to access some of the underlying SDK functionality to support all use cases.

Taking advantage of our JavaScript SDK being isomorphic, we also support SSR by using the underlying SDK in Node.js

This library also offers some extra features for users of React that are using react-redux bindings.

All of our SDKs are open source. Go to our Redux SDK GitHub repository to see the source code.

MIGRATING FROM V1.X TO V2.X

Refer to the migration guide for information on upgrading to v2.x.

Before you begin

This SDK is compatible with Redux v3 and later. It requires the redux-thunk package to be installed on the app, which is included by default if your project is using the Redux Toolkit. This means you don't need to run npm install redux-thunk if Redux Toolkit is already installed.

For react-redux users, the SDK supports its v4 and later.

In SSR setups, our library code is prepared to run in Node.js 14+.

RULE-BASED SEGMENTS SUPPORT

Rule-based segments are supported in SDK versions 2.2.0 and above. No changes are required to your SDK implementation, but updating to a supported version is required to ensure compatibility.

Older SDK versions will return the control treatment for flags using rule-based segments and log an impression with a special label for unsupported targeting rules.

Initialization

Set up FME in your code base in two steps.

1. Import the SDK into your project

The SDK is published using npm, so it's fully integrated with your workflow. You should be able to add it with yarn too.

2. Integrate the SDK in your application

You need to combine the Split reducer with yours when creating your store and use the initSplitSdk action creator, which returns a thunk, to set things in motion. You can use the combineReducers function of Redux on the splitio key. You can mount it at a different key but might require some extra code if you use the specific functionality for react-redux.

For the client side, the Redux documentation recommends creating a single store to be used as the source of truth for your state. This is where we'll plug in the Split reducer.

For Server-Side Rendering, the Redux documentation suggests creating a store per request, which is why we provide a function to create stores, where each instance will include the Split reducer.

NOTICE FOR TYPESCRIPT

With the SDK package on NPM, you get the SplitIO namespace, which contains useful types and interfaces.

Feel free to dive into the declaration files if IntelliSense is not enough!

We recommend instantiating the SDK factory once as a singleton and reusing it throughout your application.

Configure the SDK with the SDK key for the FME environment that you would like to access. In legacy Split (app.split.io) the SDK key is found on your Admin settings page, in the API keys section. Select a client-side SDK API key. This is a special type of API token with limited privileges for use in browsers or mobile clients. See API keys to learn more.

Use the SDK

The SDK via its reducer keeps a portion of the store state up to date. The state data adheres to the following schema:

Basic use

When the SDK is initialized, it starts background tasks to update an in-memory cache with small amounts of data fetched from Harness servers. This process can take up to a few hundred milliseconds depending on the size of data. If the SDK is asked to evaluate a feature flag while it's in this intermediate state, it may not have the necessary data and will queue the evaluation until it is ready.

To make sure the SDK is fully loaded before using a treatment, wait until the SDK factory client is ready. You can check SDK readiness in one of the following ways:

  • Provide an onReady callback as a parameter to the initSplitSdk function.

  • Check the isReady property of the splitio Redux state.

  • Check if the initSplitSdk returned promise is resolved.

  • Check the isReady property from the splitio selector result.

After the SDK is ready, you can use the SDK to evaluate feature flags.

The getTreatments action creator evaluates feature flag treatments for the given splitNames (array of feature flag names) and key (e.g., user or account ID) values. In the browser, the key value is taken from the configuration and bound to the client, so you don't need to pass it here unless you need to change the key.

If the SDK is not ready when you dispatch the getTreatments action, the library queues that evaluation and loads the result into the state once the SDK_READY event is emitted. If you happen to queue more than one evaluation for the same splitName and key the SDK will keep the latest set of attributes and evaluate only once.

After feature flag treatments are part of the state, use the splitio.treatments slice of state or our selectors to access the feature flag evaluation results and write the code for the different treatments that you defined in Harness FME. Remember to handle the client returning control in your code.

Note that these treatments won't be updated automatically when there is a change to your feature flags or segments. This is to avoid flickering. If you want to react to SDK events, see the Subscribe to events section below.

Attribute syntax

To target based on custom attributes, the SDK's getTreatments action creator needs to be passed an attribute map at runtime.

In the example below, we are rolling out a feature flag to users. The provided attributes plan_type, registered_date, permissions, paying_customer, and deal_size are passed to the getTreatments action creator call. These attributes are compared and evaluated against the attributes used in the rollout plan as defined in Harness FME to decide whether to show the on or off treatment to this account.

The SDK supports five types of attributes: strings, numbers, dates, booleans, and sets. The data type and syntax for each are:

  • Strings: Use type String.

  • Numbers: Use type Number.

  • **Dates: ** Use type Date and express the value in milliseconds since epoch. Note: Milliseconds since epoch is expressed in UTC. If your date or date-time combination is in a different timezone, first convert it to UTC, then transform it to milliseconds since epoch.

  • Booleans: Use type Boolean.

  • Sets: Use type Array.

Multiple evaluations at once

If you want to evaluate treatments for multiple feature flags at once, you can pass a list of feature flag names to the getTreatments action creator.

You can also evaluate multiple feature flags at once using flag sets. In that case, you can use the flagSets property instead of the splitNames property when calling the getTreatments action creator. Like splitNames, the flagSets property must be an array of string, each one corresponding to a different flag set name.

For retrieving the treatments from the store, you can use the selectTreatmentAndStatus selector. Note that this selector retrieves a single treatment value for a given feature flag name, so you need to call it for each feature flag name.

Handling control treatment flicker on SDK initialization

When implementing the Redux SDK, using the isReady prop is intended to guarantee that treatments returned are accurate. However, there can be a brief moment right after the SDK factory initializes when isReady is true but the treatment returned is control. This treatment quickly flips to the expected value (e.g. on).

This flickering occurs because when the SDK starts, it downloads the feature flag cache asynchronously from the Harness FME servers, and during that download phase, isReady may be set to true before the cache is fully loaded. If you fetch treatments too early, you receive the control treatment.

To address this, instead of dispatching getTreatments inside the onReady callback, it’s recommended to dispatch the getTreatments action immediately after initSplitSdk. This action is an asynchronous (Thunk) call that evaluates feature flags once the SDK is ready and also on subsequent SDK updates if you enable the evalOnUpdate parameter (which is false by default). This approach updates the isReady flag and treatment values together in a single action, preventing flicker caused by separate updates.

For example:

Get Treatments with Configurations

To leverage dynamic configurations with your treatments, you don't need to call a specific action creator for your evaluations. Instead, our SDK stores both the treatment and the associated config (or null if there isn't one) in the Redux state. To access this values you can either use the selectTreatmentWithConfigAndStatus selector (recommended) or just access the config from the state.

Each evaluation entry loaded into the state under the treatments key will have the structure below:

As you can see from the object structure, the config will be a stringified version of the configuration JSON defined in Harness FME. If there is no configuration defined for a treatment, the SDK will return null for the config parameter.

The selectTreatmentWithConfigAndStatus selector takes the exact same set of arguments as selectTreatmentAndStatus, as shown below.

Append properties to impressions

Impressions are generated by the SDK each time an evaluation is done using the getTreatments action creator. These impressions are periodically sent back to Harness servers for feature monitoring and experimentation.

You can append properties to an impression by passing an object of key-value pairs to the getTreatments action creator. These properties are then included in the impression sent by the SDK and can provide useful context to the impression data.

Three types of properties are supported: strings, numbers, and booleans.

Shutdown

Call the destroySplitSdk function to gracefully shutdown the SDK by stopping all background threads, clearing caches, closing connections, and flushing the remaining unpublished impressions. This function can be used as an action creator to update the splitio slice.

After destroySplitSdk() is dispatched and resolved, the evaluated treatments at the store will keep their current treatment values. However, if there is any subsequent attempt to use the getTreatments action creator, the treatments will be updated to control to be consistent with the JavaScript SDK. Also, the SDK manager methods will result in empty values.

Track

You can use the track method to record any actions your users perform. Each action is known as an event and corresponds to an event type. Calling track through one of our SDKs or via the API is the first step to getting experimentation data into Harness FME and allows you to measure the impact of your feature flags on your users’ actions and metrics. Go to Events to learn more about using track events in feature flags.

The track method takes a params object with up to five arguments. The data type and syntax for each are:

  • key: The key variable used in the getTreatments call and firing this track event. The expected data type is String.

  • TRAFFIC_TYPE: The traffic type of the key in the track call. The expected data type is String. You can only pass values that match the names of traffic types that you have defined Harness FME.

  • EVENT_TYPE: The event type that this event should correspond to. The expected data type is String. Full requirements on this argument are:

    • Contains 63 characters or fewer.

    • Starts with a letter or number.

    • Contains only letters, numbers, hyphen, underscore, or period.

    • This is the regular expression we use to validate the value: [a-zA-Z0-9][-_\.a-zA-Z0-9]{0,62}

  • VALUE: (Optional) The value to be used in creating the metric. This field can be sent in as null or 0 if you intend to purely use the count function when creating a metric. The expected data type is Integer or Float.

  • PROPERTIES: (Optional) An object of key value pairs that can be used to filter your metrics. Learn more about event property capture in the Events guide. FME currently supports three types of properties: strings, numbers, and booleans.

The track method returns a boolean value of true or false to indicate whether or not the SDK was able to successfully queue the event to be sent back to Harness servers on the next event post. The SDK returns false if the current queue size is equal to the config set by eventsQueueSize or if an incorrect input to the track method has been provided.

It is important to mention that this method does not interact with the Redux store. It's only an abstraction on top of the underlying SDK track method, so you can only import one Split package.

Configuration

The SDK has a number of parameters for configuring performance. Each parameter is set to a reasonable default. However, you can override these value in the config object passed to the initSplitSdk action creator, as shown in the Initialization section above.

To learn about all the available configuration options, go to the JavaScript SDK Configuration section.

Localhost mode

For testing, a developer can put code behind feature flags on their development machine without the SDK requiring network connectivity. To do this, start the SDK in localhost mode (also called off-the-grid or offline mode). In this mode, the SDK neither polls or updates from Harness servers. Instead, it uses an in-memory data structure to determine what treatments to show to the logged in customer for each of the features.

When instantiating the SDK in localhost mode, your authorizationKey is "localhost". Define the feature flags you want to use in the features object map. All feature flag evaluations with getTreatments actions return the one treatment (and config, if defined) that you have defined in the map. You can then change the treatment as necessary for your testing. If you want to update a treatment or a config, or to add or remove feature flags from the mock cache, update the properties of the features object you've provided. The SDK simulates polling for changes and updates from it. Do not assign a new object to the features property because the SDK has a reference to the original object and will not detect the change.

Any feature flag that is not provided in the features map returns the control treatment if the SDK is asked to evaluate them. Use the following additional configuration parameters when instantiating the SDK in localhost mode:

Configuration

Description

Default value

scheduler.offlineRefreshRate

The refresh interval for the mocked feature flags treatments.

15

features

A fixed mapping of which treatment to show for our mocked feature flags.

{} By default we have no mocked feature flags.

To use the SDK in localhost mode, replace the SDK Key with "localhost", as shown in the following test example. Note that you can define the object between a feature flag name and treatment directly or use a map to define both a treatment and a dynamic configuration.

If you define just a string as the value for a feature flag name, the config returned by the SDK is null. If you use a map, the SDK returns the specified treatment and the specified config, which can also be null.

For a complete unit test example using Jest and React Testing Library, check App.test.js.

Manager

Use the Split Manager to get a list of feature flags available to the SDK factory client. The Manager uses the data fetched from Harness servers upon SDK initialization, so you should wait for the SDK to be ready after initialization (as explained in the basic use section) before using the manager; otherwise, the manager functions will return null values and empty arrays.

You can access the manager functionality through the exposed getSplitNames, getSplit, and getSplits helper functions, as explained below.

Example usage:

For more details on about using the Manager, go to JavaScript SDK Manager.

Listener

FME SDKs send impression data back to Harness servers periodically and as a result of evaluating feature flags. To additionally send this information to a location of your choice, define and attach an impression listener. For that purpose, the SDK's configurations have a parameter called impressionListener where an implementation of ImpressionListener could be added. This implementation must define the logImpression method and it receives data in the following schema.

Name

Type

Description

impression

Object

attributes

Object

A map of attributes used on the evaluation (if any).

sdkLanguageVersion

String

The version of the SDK. In this case the language is redux plus the version of the underlying SDK.

NOTE

There are two additional keys on this object, ip and hostname. They are not used on the browser.

Implement custom impression listener

You can implement a custom impression listener as shown in the example below.

An impression listener is called asynchronously from the corresponding evaluation, but is almost immediate.

Even though the SDK does not fail if there is an exception in the listener, do not block the call stack.

Logging

To enable SDK logging in the browser, see how the SDK Logging works on the client side or the server side depending on where you're running the SDK.

Advanced use cases

This section describes advanced use cases and features provided by the Redux SDK.

Instantiate multiple SDK clients

When running on the client side the Redux SDK factory client is tied to one specific key or ID at a time which usually belongs to one traffic type (for example, user, account, organization). This enhances performance and reduces caching data in the SDK.

FME supports the ability to release features to multiple keys with different traffic types. With traffic types, you can release to users in one feature flag and accounts in another. Go to Traffic type to learn more.

If you need to roll out feature flags by different traffic types, the SDK instantiates multiple clients, one for each traffic type. For example, you may want to roll out the feature flag user-poll by users and the feature flag account-permissioning by accounts.

You can do this by providing a new key to be used when triggering evaluations or tracking events. See some examples below:

NUMBER OF SDK INSTANCES

While the SDK does not put any limitations on the number of instances that can be created, we strongly recommend keeping the number of SDKs down to one or two.

Subscribe to events

The underlying JavaScript SDK has four different events:

  • SDK_READY_FROM_CACHE. This event fires in client-side code if you are using the LOCALSTORAGE storage type and the SDK is ready to evaluate treatments using a version of your rollout plan cached from a previous session, which may be stale. By default, the localStorage API is used to cache the rollout plan (see Configuration for more information). If data is cached, this event fires almost immediately since access to localStorage is fast; otherwise, it doesn't fire.

  • SDK_READY. This event fires once the SDK is ready to evaluate treatments using the most up-to-date version of your rollout plan, downloaded from Harness servers.

  • SDK_READY_TIMED_OUT. This event fires if the SDK could not download the data from Harness servers within the time specified by the startup.readyTimeout configuration parameter. This event does not indicate that the SDK initialization was interrupted. The SDK continues downloading the rollout plan and fires the SDK_READY event when finished. This delayed SDK_READY event may happen with slow connections or large rollout plans with many feature flags, segments, or dynamic configurations.

  • SDK_UPDATE. This event fires whenever your rollout plan is changed. Listen for this event to refresh your app whenever a feature flag or segment is changed in Harness FME.

Besides managing SDK_READY on initialization, as explained in the basic use section, you can also add callbacks for the other events as shown below:

You can also access the readiness state of any SDK factory client with the selectStatus selector, or when retrieving treatments with the selectTreatmentAndStatus or selectTreatmentWithConfigAndStatus selectors.

You can also do this from the store directly.

The getTreatments action creator accepts two optional parameters, evalOnUpdate and evalOnReadyFromCache, which are false by default to avoid unwanted flickering. These parameters are only for client side and will be ignored if set on the server side.

When evalOnUpdate is explicitly set to true, the given treatment will be re-evaluated in the event of an SDK_UPDATE being triggered by the underlying SDK. You can use it to re-render your components whenever there is a change due to a rollout update or a feature flag being killed.

When evalOnReadyFromCache is explicitly set to true, the given treatment will be re-evaluated in the event of an SDK_READY_FROM_CACHE being triggered by the underlying SDK. Therefore, this param is only relevant when using 'LOCALSTORAGE' as storage type, since otherwise the event is never emitted.

Keep in mind that if there was no cache previously loaded on the browser or the event has already fired, this parameter will take no effect. Also, consider that when evaluating from cache you might be using a stale snapshot until the SDK is ready.

Usage with React + Redux

We provide extra functionality for users of react-redux with two High Order Components (HOCs). In the future we'll add more mapState functions for your convenience.

The connectSplit HOC connects a given component with the splitio slice and getTreatments action creator already bound to the dispatch, so you don't need to dispatch that action yourself.

The connectToggler HOC simplifies toggling when you have a component version for "on" treatment and a different one for any other treatments (including "control"). For example:

The SDK factory allows you to disable the tracking of events and impressions until user consent is explicitly granted or declined. To learn how to configure this feature, refer to the JavaScript SDK User consent section.

When using the Redux SDK, you can access the underlying SDK factory instance via the splitSdk object, as shown below:

Example apps

The following example application shows how you can integrate the React SDK into your code.

Last updated

Was this helpful?