diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index a562ba4b6bf..9453c2539d7 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -914,6 +914,16 @@ const definitions: FeatureFlagDefinitions = { }, ossReleaseStage: 'none', }, + virtualViewActivityBehavior: { + defaultValue: 'no-activity', + metadata: { + dateAdded: '2025-08-27', + description: 'Changes whether and how `VirtualView` uses `Activity`.', + expectedReleaseValue: true, + purpose: 'experimentation', + }, + ossReleaseStage: 'none', + }, }, }; diff --git a/packages/react-native/src/private/components/virtualview/VirtualView.js b/packages/react-native/src/private/components/virtualview/VirtualView.js index ffeff6e43fe..d2330da72f0 100644 --- a/packages/react-native/src/private/components/virtualview/VirtualView.js +++ b/packages/react-native/src/private/components/virtualview/VirtualView.js @@ -14,11 +14,13 @@ import type {HostInstance} from '../../types/HostInstance'; import type {NativeModeChangeEvent} from './VirtualViewNativeComponent'; import StyleSheet from '../../../../Libraries/StyleSheet/StyleSheet'; +import * as ReactNativeFeatureFlags from '../../featureflags/ReactNativeFeatureFlags'; import VirtualViewExperimentalNativeComponent from './VirtualViewExperimentalNativeComponent'; import VirtualViewNativeComponent from './VirtualViewNativeComponent'; import nullthrows from 'nullthrows'; import * as React from 'react'; -import {startTransition, useState} from 'react'; +// $FlowFixMe[missing-export] +import {startTransition, unstable_Activity as Activity, useState} from 'react'; // @see VirtualViewNativeComponent export enum VirtualViewMode { @@ -140,7 +142,17 @@ function createVirtualView( : style } onModeChange={handleModeChange}> - {isHidden ? null : children} + { + match (ReactNativeFeatureFlags.virtualViewActivityBehavior()) { + 'activity-without-mode' => + {isHidden ? null : children}, + 'activity-with-hidden-mode' => + + {children} + , + 'no-activity' | _ => isHidden ? null : children, + } + } ); } diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 065614781ea..929699d8c8c 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<276b1579eef10e63c77752017b97985f>> + * @generated SignedSource<<85a053d6a79240a7b4e181d3054ecfd3>> * @flow strict * @noformat */ @@ -41,6 +41,7 @@ export type ReactNativeFeatureFlagsJsOnly = $ReadOnly<{ shouldUseAnimatedObjectForTransform: Getter, shouldUseRemoveClippedSubviewsAsDefaultOnIOS: Getter, shouldUseSetNativePropsInFabric: Getter, + virtualViewActivityBehavior: Getter, }>; export type ReactNativeFeatureFlagsJsOnlyOverrides = OverridesFor; @@ -184,6 +185,11 @@ export const shouldUseRemoveClippedSubviewsAsDefaultOnIOS: Getter = cre */ export const shouldUseSetNativePropsInFabric: Getter = createJavaScriptFlagGetter('shouldUseSetNativePropsInFabric', true); +/** + * Changes whether and how `VirtualView` uses `Activity`. + */ +export const virtualViewActivityBehavior: Getter = createJavaScriptFlagGetter('virtualViewActivityBehavior', "no-activity"); + /** * Common flag for testing. Do NOT modify. */ diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlagsBase.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlagsBase.js index 050b003a2ef..89b8e9042bc 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlagsBase.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlagsBase.js @@ -61,6 +61,7 @@ export function createJavaScriptFlagGetter< configName, () => { accessedFeatureFlags.add(configName); + // $FlowFixMe[incompatible-type] - `defaultValue` is not refined. return overrides?.[configName]?.(defaultValue); }, defaultValue,