Skip to main content
Version: 4.x

Feature flags

Feature flags allow developers to opt-in for experimental changes or opt-out from recent changes that have already been made default. Feature flags serve as a tool for incremental rollout of new implementation without affecting the general stability of the library, allowing to gather feedback from early adopters. There are two types of feature flags: static and dynamic.

info

Feature flags are available since Reanimated 4.

Summary of available feature flags

Feature flag nameTypeAdded inRemoved inDefault value
DISABLE_COMMIT_PAUSING_MECHANISMstatic4.0.0false
ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPSstatic4.0.0false
EXPERIMENTAL_CSS_ANIMATIONS_FOR_SVG_COMPONENTSstatic4.1.0false
EXPERIMENTAL_MUTABLE_OPTIMIZATIONdynamic4.1.0false
info

Feature flags available in react-native-worklets are listed on this page.

Description of available feature flags

DISABLE_COMMIT_PAUSING_MECHANISM

When enabled, this feature flag is supposed to eliminate jittering of animated components like sticky header while scrolling. This feature flag is safe to enable only if preventShadowTreeCommitExhaustion feature flag from react-native (available since React Native 0.81) is also enabled. In all other cases it can lead to unresponsiveness of the app due to the starvation of React commits. For more details, see PR #7852.

ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS

When enabled, non-layout styles will be applied using the synchronouslyUpdateViewOnUIThread method (which doesn't involve layout recalculation) instead of than ShadowTree::commit method (which requires layout recalculation). In an artifical benchmark, it can lead to up to 4x increase of frames per second. Even though we don't expect such high speedups in the production apps, there should be a visible improvements in the smoothness of some animations. However, there are some unwanted side effects that one needs to take into account and properly compensate for:

  1. The changes applied via synchronouslyUpdateViewOnUIThread are not respected by the touch gesture system of Fabric renderer which can lead to incorrect behavior, in particular if transforms are applied. In that case, it's advisable to use Pressable component from react-native-gesture-handler (which attaches to the underlying platform view rather than using ShadowTree to determine the component present at given point) rather than its original counterpart from react-native.

  2. The changes are applied via synchronouslyUpdateViewOnUIThread are not synchronized with changes applied by ShadowTree::commit which may lead to minor inconsistencies of animated styles or animated components in a single animation frame.

Currently, only the following styles can be updated using the fast path: opacity, elevation, zIndex, backgroundColor, tintColor, borderRadius (all sides), borderColor (all sides) and transform (all transforms). All remaining styles, if present, will be updated via ShadowTree::commit.

This feature flag works only on Android and has no effect on iOS. For more details, see PR #7823.

EXPERIMENTAL_CSS_ANIMATIONS_FOR_SVG_COMPONENTS

When enabled, CSS animations and transitions will also work for a limited set of props of several components from react-native-svg library. Currently, Circle, Ellipse, Line, Path and Rect components are supported.

Static feature flags

Static flags are intended to be resolved during code compilation and cannot be changed during application runtime. To enable a static feature flag, you need to:

  1. Add the following lines to package.json of your app
{
// ...
"reanimated": {
"staticFeatureFlags": {
"EXAMPLE_STATIC_FLAG": true
}
}
}
  1. Run pod install (iOS only)
  2. Rebuild the native app

To read a static feature flag value in JavaScript, you can use getStaticFeatureFlag function.

Dynamic feature flags

Dynamic flags can be modified during runtime and their values can change at any moment of app lifetime. To enable or disable a dynamic feature flag, you need to call setDynamicFeatureFlag function.

import { setDynamicFeatureFlag } from 'react-native-reanimated';

setDynamicFeatureFlag('EXAMPLE_DYNAMIC_FLAG', true);

Comparison of static and dynamic feature flags

Static feature flagsDynamic feature flags
Value is known during app build
Value may change during app lifetime
Value change requires app rebuild
Can be changed via public JavaScript API
Can be changed via app's package.json

Remarks for contributors

  • Feature flags should switch the implementation to the new experimental behavior only when enabled.
  • Initially, the default value should be false, allowing users to opt-in for the experimental behavior when desired.
  • When the experimental behavior is considered stable, the default value should be set to true, while still allowing users to opt-out if needed.
  • After some period, the feature flag which is enabled by default should be removed from the codebase.
  • Both static and dynamic feature flags should follow upper snake case, i.e. EXAMPLE_FEATURE_FLAG.
  • The name of the feature flag should not contain the expression FEATURE_FLAG itself.
  • It is recommended to explicitly use ENABLE_ or DISABLE_ prefix for feature flags that enable or disable certain parts of the code for the sake of clarity.