Skip to content

Commit 520938e

Browse files
Generate initialHidden as an optional prop for VirtualView (#58864)
Summary: `VirtualViewNativeComponent` declared `initialHidden?: boolean`, which codegen generated as a plain `bool` defaulting to `false`. On Android, props equal to their C++ default are not sent when a view is created, so an explicit `initialHidden={false}` never reached `ReactVirtualViewManager.setInitialHidden`. The view's `mode` stayed `null`, so it emitted a synchronous `Visible` mode change on its first update, emitted a normally suppressed `Prerender` change, and skipped the clipping update when it first left `Visible`. Declare the prop as `WithDefault<boolean, null>` and opt the spec into `generateOptionalProperties`, so `initialHidden` is a `std::optional<bool>` that is unset by default and an explicit `false` is sent. A plain `?: boolean` is not enough, because the Flow parser assigns it a `false` default. The `codegenNativeComponent` Flow options type gains the codegen options already declared in its TypeScript types, and iOS reads the prop with `value_or(false)`. This changes generated APIs of VirtualView: `VirtualViewProps::initialHidden` becomes `std::optional<bool>`, and `VirtualViewManagerInterface.setInitialHidden` takes a nullable `Boolean`. The public JS API change is additive: `NativeComponentOptions` gains the optional `generateOptionalProperties` and `generateOptionalObjectProperties` fields, so the API snapshot reports `codegenNativeComponent` as changed without breaking existing callers. Changelog: [General][Fixed] - Fix `VirtualView` initial mode when `initialHidden` is not sent on creation Reviewed By: javache Differential Revision: D123029234
1 parent a4c421a commit 520938e

14 files changed

Lines changed: 23 additions & 17 deletions

File tree

‎packages/react-native/Libraries/Utilities/codegenNativeComponent.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ type NativeComponentOptions = Readonly<{
2121
paperComponentName?: string,
2222
paperComponentNameDeprecated?: string,
2323
excludedPlatforms?: ReadonlyArray<'iOS' | 'android'>,
24+
generateOptionalProperties?: boolean,
25+
generateOptionalObjectProperties?: boolean,
2426
}>;
2527

2628
// Note that this alias is not re-exported from the `react-native` root,

‎packages/react-native/React/Fabric/Mounting/ComponentViews/VirtualView/RCTVirtualViewComponentView.mm‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &
6363
const auto &newViewProps = static_cast<const VirtualViewProps &>(*props);
6464

6565
if (!_mode.has_value()) {
66-
_mode = newViewProps.initialHidden ? RCTVirtualViewModeHidden : RCTVirtualViewModeVisible;
66+
_mode = newViewProps.initialHidden.value_or(false) ? RCTVirtualViewModeHidden : RCTVirtualViewModeVisible;
6767
}
6868

6969
switch (newViewProps.renderState) {

‎packages/react-native/ReactAndroid/api/ReactAndroid.api‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5152,7 +5152,7 @@ public class com/facebook/react/viewmanagers/VirtualViewManagerDelegate : com/fa
51525152
}
51535153

51545154
public abstract interface class com/facebook/react/viewmanagers/VirtualViewManagerInterface : com/facebook/react/uimanager/ViewManagerWithGeneratedInterface {
5155-
public abstract fun setInitialHidden (Landroid/view/View;Z)V
5155+
public abstract fun setInitialHidden (Landroid/view/View;Ljava/lang/Boolean;)V
51565156
public abstract fun setRemoveClippedSubviews (Landroid/view/View;Z)V
51575157
public abstract fun setRenderState (Landroid/view/View;I)V
51585158
}
@@ -6580,8 +6580,8 @@ public final class com/facebook/react/views/virtual/view/ReactVirtualViewManager
65806580
public synthetic fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Landroid/view/View;
65816581
public fun getName ()Ljava/lang/String;
65826582
public synthetic fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)Landroid/view/View;
6583-
public synthetic fun setInitialHidden (Landroid/view/View;Z)V
6584-
public fun setInitialHidden (Lcom/facebook/react/views/virtual/view/ReactVirtualView;Z)V
6583+
public synthetic fun setInitialHidden (Landroid/view/View;Ljava/lang/Boolean;)V
6584+
public fun setInitialHidden (Lcom/facebook/react/views/virtual/view/ReactVirtualView;Ljava/lang/Boolean;)V
65856585
public synthetic fun setNativeId (Landroid/view/View;Ljava/lang/String;)V
65866586
public fun setNativeId (Lcom/facebook/react/views/virtual/view/ReactVirtualView;Ljava/lang/String;)V
65876587
public synthetic fun setRemoveClippedSubviews (Landroid/view/View;Z)V

‎packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/virtual/view/ReactVirtualViewManager.kt‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ public class ReactVirtualViewManager :
3737
ReactVirtualView(reactContext)
3838

3939
@ReactProp(name = "initialHidden")
40-
override fun setInitialHidden(view: ReactVirtualView, value: Boolean) {
40+
override fun setInitialHidden(view: ReactVirtualView, value: Boolean?) {
4141
if (view.mode == null) {
42-
view.mode = if (value) VirtualViewMode.Hidden else VirtualViewMode.Visible
42+
view.mode = if (value == true) VirtualViewMode.Hidden else VirtualViewMode.Visible
4343
}
4444
}
4545

‎packages/react-native/ReactNativeApi.d.ts‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<6d379de092b8bad36a420658bbc25a6d>>
7+
* @generated SignedSource<<c7bfb58714c5cd50a054ec7a0090b3f8>>
88
*
99
* This file was generated by scripts/js-api/build-types/index.js.
1010
*/
@@ -3072,6 +3072,8 @@ declare type NativeCommandsOptions<T = string> = {
30723072
}
30733073
declare type NativeComponentOptions = {
30743074
readonly excludedPlatforms?: ReadonlyArray<"android" | "iOS">
3075+
readonly generateOptionalObjectProperties?: boolean
3076+
readonly generateOptionalProperties?: boolean
30753077
readonly interfaceOnly?: boolean
30763078
readonly paperComponentName?: string
30773079
readonly paperComponentNameDeprecated?: string
@@ -6055,7 +6057,7 @@ export {
60556057
VirtualizedSectionListProps, // 8373f27c
60566058
WrapperComponentProvider, // 9b4247f6
60576059
codegenNativeCommands, // 322f3f4e
6058-
codegenNativeComponent, // e8334853
6060+
codegenNativeComponent, // 3da62daa
60596061
findNodeHandle, // 93f80214
60606062
processColor, // 6e877698
60616063
registerCallableModule, // 839c8cfe

‎packages/react-native/src/private/components/virtualview/VirtualViewNativeComponent.js‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type {
1313
DirectEventHandler,
1414
Double,
1515
Int32,
16+
WithDefault,
1617
} from '../../../../Libraries/Types/CodegenTypes';
1718
import type {HostComponent} from '../../types/HostComponent';
1819

@@ -65,7 +66,7 @@ type VirtualViewNativeProps = Readonly<{
6566
/**
6667
* Whether the initial mode should be `Hidden`.
6768
*/
68-
initialHidden?: boolean,
69+
initialHidden?: WithDefault<boolean, null>,
6970

7071
/**
7172
* This was needed to get VirtualViewManagerDelegate to set this property.
@@ -93,4 +94,5 @@ type VirtualViewNativeProps = Readonly<{
9394

9495
export default codegenNativeComponent<VirtualViewNativeProps>('VirtualView', {
9596
interfaceOnly: true,
97+
generateOptionalProperties: true,
9698
}) as HostComponent<VirtualViewNativeProps>;

‎scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2575,9 +2575,9 @@ struct facebook::react::VirtualViewEventEmitter::OnModeChangeThresholdRect {
25752575
class facebook::react::VirtualViewProps : public facebook::react::HostPlatformViewProps {
25762576
public VirtualViewProps() = default;
25772577
public VirtualViewProps(const facebook::react::PropsParserContext& context, const facebook::react::VirtualViewProps& sourceProps, const facebook::react::RawProps& rawProps);
2578-
public bool initialHidden;
25792578
public bool removeClippedSubviews;
25802579
public int renderState;
2580+
public std::optional<bool> initialHidden;
25812581
public virtual facebook::react::ComponentName getDiffPropsImplementationTarget() const override;
25822582
public virtual folly::dynamic getDiffProps(const facebook::react::Props* prevProps) const override;
25832583
}

‎scripts/cxx-api/api-snapshots/ReactAndroidFrameworksCxx.api‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4415,9 +4415,9 @@ struct facebook::react::VirtualViewEventEmitter::OnModeChangeThresholdRect {
44154415
class facebook::react::VirtualViewProps : public facebook::react::HostPlatformViewProps {
44164416
public VirtualViewProps() = default;
44174417
public VirtualViewProps(const facebook::react::PropsParserContext& context, const facebook::react::VirtualViewProps& sourceProps, const facebook::react::RawProps& rawProps);
4418-
public bool initialHidden;
44194418
public bool removeClippedSubviews;
44204419
public int renderState;
4420+
public std::optional<bool> initialHidden;
44214421
public virtual facebook::react::ComponentName getDiffPropsImplementationTarget() const override;
44224422
public virtual folly::dynamic getDiffProps(const facebook::react::Props* prevProps) const override;
44234423
}

‎scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2568,9 +2568,9 @@ struct facebook::react::VirtualViewEventEmitter::OnModeChangeThresholdRect {
25682568
class facebook::react::VirtualViewProps : public facebook::react::HostPlatformViewProps {
25692569
public VirtualViewProps() = default;
25702570
public VirtualViewProps(const facebook::react::PropsParserContext& context, const facebook::react::VirtualViewProps& sourceProps, const facebook::react::RawProps& rawProps);
2571-
public bool initialHidden;
25722571
public bool removeClippedSubviews;
25732572
public int renderState;
2573+
public std::optional<bool> initialHidden;
25742574
public virtual facebook::react::ComponentName getDiffPropsImplementationTarget() const override;
25752575
public virtual folly::dynamic getDiffProps(const facebook::react::Props* prevProps) const override;
25762576
}

‎scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2568,9 +2568,9 @@ struct facebook::react::VirtualViewEventEmitter::OnModeChangeThresholdRect {
25682568
class facebook::react::VirtualViewProps : public facebook::react::HostPlatformViewProps {
25692569
public VirtualViewProps() = default;
25702570
public VirtualViewProps(const facebook::react::PropsParserContext& context, const facebook::react::VirtualViewProps& sourceProps, const facebook::react::RawProps& rawProps);
2571-
public bool initialHidden;
25722571
public bool removeClippedSubviews;
25732572
public int renderState;
2573+
public std::optional<bool> initialHidden;
25742574
public virtual facebook::react::ComponentName getDiffPropsImplementationTarget() const override;
25752575
public virtual folly::dynamic getDiffProps(const facebook::react::Props* prevProps) const override;
25762576
}

0 commit comments

Comments
 (0)