Skip to content

Commit d8e0c29

Browse files
NickGerlemanroryabraham
authored andcommitted
Add VirtualizedList_EXPERIMENTAL (CellRenderMask Usage)
Summary: # This Change react-native-community/discussions-and-proposals#335 discussed a set of problems with VirtualizedList and focus. These were seen as severe externally for a11y on desktop. The issues center on users of keyboard and accessibility tools, where users expect to be able to move focus in an uninterrupted loop. The design and implementation evolved to be a bit more general, and without any API-surface behavior changes. It was implemented and rolled out externally as a series of changes. The remaining changes that were not upstreamed into RN are rolled into facebook#32646 This diff brings this change into the repo, as a separate copy of VirtualizedList, to measure its impact to guardrail metrics, without yet making it the default implementation. The intention is for this to be temporary, until there is confidence the implementation is correct. ## List Implementation (more on GitHub) This change makes it possible to synchronously move native focus to arbitrary items in a VirtualizedList. This is implemented by switching component state to a sparse bitset. This was previously implemented and upstreamed as `CellRenderMask`. A usage of this is added, to keep the last focused item rendered. This allows the focus loop to remain unbroken, when scrolling away, or tab loops which leave/re-enter the list. VirtualizedList tracks the last focused cell through the capture phase of `onFocus`. It will keep the cell, and a viewport above and below the last focused cell rendered, to allow movement to it without blanking (without using too much memory). ## Experimentation Implementation A mechanism is added to gate the change via VirtualizedListInjection, mirroring the approach taken for Switch with D27381306 (facebook@683b825). It allows VirtualizedList to delegate to a global override. It has a slight penalty to needing to import both modules, but means code which imports VirtualizedList directly is affected the changes. Changelog: [Internal][Added] - Add VirtualizedList_EXPERIMENTAL (CellRenderMask Usage) Reviewed By: lunaleaps Differential Revision: D38020408 fbshipit-source-id: ad0aaa6791f3f4455e3068502a2841f3ffb40b41
1 parent 4d9664e commit d8e0c29

8 files changed

+8008
-5
lines changed

Libraries/Lists/CellRenderMask.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ export class CellRenderMask {
110110
);
111111
}
112112

113+
numCells(): number {
114+
return this._numCells;
115+
}
116+
113117
equals(other: CellRenderMask): boolean {
114118
return (
115119
this._numCells === other._numCells &&

Libraries/Lists/VirtualizeUtils.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ export function computeWindowedRenderLimits(
102102
prev: {
103103
first: number,
104104
last: number,
105-
...
106105
},
107106
getFrameMetricsApprox: (index: number) => {
108107
length: number,
@@ -120,7 +119,6 @@ export function computeWindowedRenderLimits(
120119
): {
121120
first: number,
122121
last: number,
123-
...
124122
} {
125123
const itemCount = getItemCount(data);
126124
if (itemCount === 0) {

Libraries/Lists/VirtualizedList.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2217,4 +2217,5 @@ const styles = StyleSheet.create({
22172217
},
22182218
});
22192219

2220-
module.exports = VirtualizedList;
2220+
module.exports = (require('./VirtualizedListInjection').default
2221+
.unstable_VirtualizedList ?? VirtualizedList: typeof VirtualizedList);
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
8+
* @format
9+
*/
10+
11+
'use strict';
12+
import typeof VirtualizedList from './VirtualizedList';
13+
14+
export default {
15+
unstable_VirtualizedList: (null: ?VirtualizedList),
16+
};

0 commit comments

Comments
 (0)