Skip to content

Commit 2d985f1

Browse files
Generate initialHidden as an optional prop for VirtualView
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`. Changelog: [General][Fixed] - Fix `VirtualView` initial mode when `initialHidden` is not sent on creation Differential Revision: D123029234
1 parent 52efed6 commit 2d985f1

12 files changed

Lines changed: 21 additions & 15 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
}
@@ -6579,8 +6579,8 @@ public final class com/facebook/react/views/virtual/view/ReactVirtualViewManager
65796579
public synthetic fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Landroid/view/View;
65806580
public fun getName ()Ljava/lang/String;
65816581
public synthetic fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)Landroid/view/View;
6582-
public synthetic fun setInitialHidden (Landroid/view/View;Z)V
6583-
public fun setInitialHidden (Lcom/facebook/react/views/virtual/view/ReactVirtualView;Z)V
6582+
public synthetic fun setInitialHidden (Landroid/view/View;Ljava/lang/Boolean;)V
6583+
public fun setInitialHidden (Lcom/facebook/react/views/virtual/view/ReactVirtualView;Ljava/lang/Boolean;)V
65846584
public synthetic fun setNativeId (Landroid/view/View;Ljava/lang/String;)V
65856585
public fun setNativeId (Lcom/facebook/react/views/virtual/view/ReactVirtualView;Ljava/lang/String;)V
65866586
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<<3ce9599aceb36dd1f09ded3db3332daa>>
7+
* @generated SignedSource<<9fc1cc10ed7a503cbe222b553cdf4d3d>>
88
*
99
* This file was generated by scripts/js-api/build-types/index.js.
1010
*/
@@ -3076,6 +3076,8 @@ declare type NativeCommandsOptions<T = string> = {
30763076
}
30773077
declare type NativeComponentOptions = {
30783078
readonly excludedPlatforms?: ReadonlyArray<"android" | "iOS">
3079+
readonly generateOptionalObjectProperties?: boolean
3080+
readonly generateOptionalProperties?: boolean
30793081
readonly interfaceOnly?: boolean
30803082
readonly paperComponentName?: string
30813083
readonly paperComponentNameDeprecated?: string
@@ -6058,7 +6060,7 @@ export {
60586060
VirtualizedSectionListProps, // 8373f27c
60596061
WrapperComponentProvider, // 9b4247f6
60606062
codegenNativeCommands, // 322f3f4e
6061-
codegenNativeComponent, // e8334853
6063+
codegenNativeComponent, // 3da62daa
60626064
findNodeHandle, // 93f80214
60636065
processColor, // 6e877698
60646066
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
@@ -5570,9 +5570,9 @@ struct facebook::react::VirtualViewEventEmitter::OnModeChangeThresholdRect {
55705570
class facebook::react::VirtualViewProps : public facebook::react::HostPlatformViewProps {
55715571
public VirtualViewProps() = default;
55725572
public VirtualViewProps(const facebook::react::PropsParserContext& context, const facebook::react::VirtualViewProps& sourceProps, const facebook::react::RawProps& rawProps);
5573-
public bool initialHidden;
55745573
public bool removeClippedSubviews;
55755574
public int renderState;
5575+
public std::optional<bool> initialHidden;
55765576
public virtual facebook::react::ComponentName getDiffPropsImplementationTarget() const override;
55775577
public virtual folly::dynamic getDiffProps(const facebook::react::Props* prevProps) const override;
55785578
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5380,9 +5380,9 @@ struct facebook::react::VirtualViewEventEmitter::OnModeChangeThresholdRect {
53805380
class facebook::react::VirtualViewProps : public facebook::react::HostPlatformViewProps {
53815381
public VirtualViewProps() = default;
53825382
public VirtualViewProps(const facebook::react::PropsParserContext& context, const facebook::react::VirtualViewProps& sourceProps, const facebook::react::RawProps& rawProps);
5383-
public bool initialHidden;
53845383
public bool removeClippedSubviews;
53855384
public int renderState;
5385+
public std::optional<bool> initialHidden;
53865386
public virtual facebook::react::ComponentName getDiffPropsImplementationTarget() const override;
53875387
public virtual folly::dynamic getDiffProps(const facebook::react::Props* prevProps) const override;
53885388
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5561,9 +5561,9 @@ struct facebook::react::VirtualViewEventEmitter::OnModeChangeThresholdRect {
55615561
class facebook::react::VirtualViewProps : public facebook::react::HostPlatformViewProps {
55625562
public VirtualViewProps() = default;
55635563
public VirtualViewProps(const facebook::react::PropsParserContext& context, const facebook::react::VirtualViewProps& sourceProps, const facebook::react::RawProps& rawProps);
5564-
public bool initialHidden;
55655564
public bool removeClippedSubviews;
55665565
public int renderState;
5566+
public std::optional<bool> initialHidden;
55675567
public virtual facebook::react::ComponentName getDiffPropsImplementationTarget() const override;
55685568
public virtual folly::dynamic getDiffProps(const facebook::react::Props* prevProps) const override;
55695569
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7701,9 +7701,9 @@ struct facebook::react::VirtualViewEventEmitter::OnModeChangeThresholdRect {
77017701
class facebook::react::VirtualViewProps : public facebook::react::HostPlatformViewProps {
77027702
public VirtualViewProps() = default;
77037703
public VirtualViewProps(const facebook::react::PropsParserContext& context, const facebook::react::VirtualViewProps& sourceProps, const facebook::react::RawProps& rawProps);
7704-
public bool initialHidden;
77057704
public bool removeClippedSubviews;
77067705
public int renderState;
7706+
public std::optional<bool> initialHidden;
77077707
}
77087708

77097709
class facebook::react::VirtualViewShadowNode : public facebook::react::ConcreteViewShadowNode<facebook::react::VirtualViewComponentName, facebook::react::VirtualViewProps, facebook::react::VirtualViewEventEmitter> {

0 commit comments

Comments
 (0)