Skip to content

Commit d6ed32f

Browse files
yungstersfacebook-github-bot
authored andcommitted
VirtualView: Configurable Hidden Layout (#53571)
Summary: Pull Request resolved: #53571 Changes `VirtualView` so that its layout when hidden can be configured by call sites. Previously, it was hardcoded to only retain the last known height. However, this logic only works for `VirtualView` children oriented in a column layout. This change enables the use of `VirtualView` in more flexible abstractions that require different hidden styles (e.g. row or grid orientations). Also, this changes the default behavior to set `minWidth` and `minHeight`, so that the default behavior is more general and more likely to work in a reasonable manner in more use cases. NOTE: Ideally, we would be able to default to using `flexBasis` instead. However, the `hiddenStyle` function receives a `Rect` and does not know whether the parent's flex direction is row or column to influence whether to use `targetRect.width` or `targetRect.height`. This is an opportunity for future improvement. Changelog: [Internal] Reviewed By: lunaleaps Differential Revision: D81344126 fbshipit-source-id: 33d9e81601b671059f97b4590816243cbd24734a
1 parent 1604232 commit d6ed32f

2 files changed

Lines changed: 26 additions & 21 deletions

File tree

packages/react-native/src/private/components/virtualview/VirtualView.js

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,23 +56,29 @@ const VirtualViewNativeComponent: typeof VirtualViewClassicNativeComponent =
5656

5757
type VirtualViewComponent = component(
5858
children?: React.Node,
59+
hiddenStyle?: (targetRect: Rect) => ViewStyleProp,
5960
nativeID?: string,
6061
ref?: ?React.RefSetter<React.ElementRef<typeof VirtualViewNativeComponent>>,
6162
style?: ?ViewStyleProp,
6263
onModeChange?: (event: ModeChangeEvent) => void,
6364
removeClippedSubviews?: boolean,
6465
);
6566

66-
type HiddenHeight = number;
6767
const NotHidden = null;
68+
type HiddenStyle = Exclude<ViewStyleProp, typeof NotHidden>;
6869

69-
type State = HiddenHeight | typeof NotHidden;
70+
type State = HiddenStyle | typeof NotHidden;
71+
72+
function defaultHiddenStyle(targetRect: Rect): ViewStyleProp {
73+
return {minHeight: targetRect.height, minWidth: targetRect.width};
74+
}
7075

7176
function createVirtualView(initialState: State): VirtualViewComponent {
7277
const initialHidden = initialState !== NotHidden;
7378

7479
component VirtualView(
7580
children?: React.Node,
81+
hiddenStyle: (targetRect: Rect) => ViewStyleProp = defaultHiddenStyle,
7682
nativeID?: string,
7783
ref?: ?React.RefSetter<React.ElementRef<typeof VirtualViewNativeComponent>>,
7884
style?: ?ViewStyleProp,
@@ -112,9 +118,8 @@ function createVirtualView(initialState: State): VirtualViewComponent {
112118
});
113119
}
114120
VirtualViewMode.Hidden => {
115-
const {height} = event.nativeEvent.targetRect;
116121
startTransition(() => {
117-
setState(height as HiddenHeight);
122+
setState(hiddenStyle(event.nativeEvent.targetRect) ?? {});
118123
emitModeChange?.();
119124
});
120125
}
@@ -134,9 +139,7 @@ function createVirtualView(initialState: State): VirtualViewComponent {
134139
}
135140
style={
136141
isHidden
137-
? StyleSheet.compose(style, {
138-
height: Math.abs(nullthrows(state) as HiddenHeight),
139-
})
142+
? StyleSheet.compose(style, nullthrows(state) as HiddenStyle)
140143
: style
141144
}
142145
onModeChange={handleModeChange}>
@@ -159,8 +162,10 @@ function createVirtualView(initialState: State): VirtualViewComponent {
159162

160163
export default createVirtualView(NotHidden) as VirtualViewComponent;
161164

162-
export function createHiddenVirtualView(height: number): VirtualViewComponent {
163-
return createVirtualView(height as HiddenHeight);
165+
export function createHiddenVirtualView(
166+
style: ViewStyleProp,
167+
): VirtualViewComponent {
168+
return createVirtualView((style ?? {}) as HiddenStyle);
164169
}
165170

166171
export const _logs: {states?: Array<State>} = {};

packages/react-native/src/private/components/virtualview/__tests__/VirtualView-itest.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -119,19 +119,19 @@ describe('mode changes', () => {
119119
});
120120

121121
describe('styles', () => {
122-
test('does not set height when visible', () => {
122+
test('does not set styles when visible', () => {
123123
const root = Fantom.createRoot();
124124

125125
Fantom.runTask(() => {
126126
root.render(<VirtualView />);
127127
});
128128

129-
expect(root.getRenderedOutput({props: ['height']}).toJSX()).toEqual(
130-
<rn-virtualView />,
131-
);
129+
expect(
130+
root.getRenderedOutput({props: ['minHeight', 'minWidth']}).toJSX(),
131+
).toEqual(<rn-virtualView />);
132132
});
133133

134-
test('does not set height when prerendered', () => {
134+
test('does not set styles when prerendered', () => {
135135
const root = Fantom.createRoot();
136136
const viewRef = createRef<React.RefOf<VirtualView>>();
137137

@@ -141,12 +141,12 @@ describe('styles', () => {
141141

142142
dispatchModeChangeEvent(viewRef.current, VirtualViewMode.Prerender);
143143

144-
expect(root.getRenderedOutput({props: ['height']}).toJSX()).toEqual(
145-
<rn-virtualView />,
146-
);
144+
expect(
145+
root.getRenderedOutput({props: ['minHeight', 'minWidth']}).toJSX(),
146+
).toEqual(<rn-virtualView />);
147147
});
148148

149-
test('sets height when hidden', () => {
149+
test('sets styles when hidden', () => {
150150
const root = Fantom.createRoot();
151151
const viewRef = createRef<React.RefOf<VirtualView>>();
152152

@@ -156,9 +156,9 @@ describe('styles', () => {
156156

157157
dispatchModeChangeEvent(viewRef.current, VirtualViewMode.Hidden);
158158

159-
expect(root.getRenderedOutput({props: ['height']}).toJSX()).toEqual(
160-
<rn-virtualView height="100.000000" />,
161-
);
159+
expect(
160+
root.getRenderedOutput({props: ['minHeight', 'minWidth']}).toJSX(),
161+
).toEqual(<rn-virtualView minHeight="100.000000" minWidth="100.000000" />);
162162
});
163163
});
164164

0 commit comments

Comments
 (0)