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.
Feature flags are available since Reanimated 4.
Summary of available feature flags
Feature flag name | Type | Added in | Removed in | Default value |
---|---|---|---|---|
DISABLE_COMMIT_PAUSING_MECHANISM | static | 4.0.0 | – | false |
ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS | static | 4.0.0 | – | false |
EXPERIMENTAL_CSS_ANIMATIONS_FOR_SVG_COMPONENTS | static | 4.1.0 | – | false |
EXPERIMENTAL_MUTABLE_OPTIMIZATION | dynamic | 4.1.0 | – | false |
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:
-
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 usePressable
component fromreact-native-gesture-handler
(which attaches to the underlying platform view rather than usingShadowTree
to determine the component present at given point) rather than its original counterpart fromreact-native
. -
The changes are applied via
synchronouslyUpdateViewOnUIThread
are not synchronized with changes applied byShadowTree::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:
- Add the following lines to
package.json
of your app
{
// ...
"reanimated": {
"staticFeatureFlags": {
"EXAMPLE_STATIC_FLAG": true
}
}
}
- Run
pod install
(iOS only) - 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 flags | Dynamic 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_
orDISABLE_
prefix for feature flags that enable or disable certain parts of the code for the sake of clarity.