Avoid excessive re-render of room list and member list (#31131)

* fix(list view): avoid re-create `onFocus` function at each render of the child items

* fix(room list): update `onFocus` signature

* fix(member list): update `onFocus` signature

* fix(room list): avoid re-render at the beginning and end of the scroll

* test(room list): remove scrolling test and props

* test(member list): update member tile view tests

* test(room list): update `ListView` focus test

* test(member list): add `onFocus` test for member list tile
This commit is contained in:
Florian Duros
2025-10-30 14:55:15 +00:00
committed by GitHub
parent f297282bf6
commit 299d7baf8b
9 changed files with 97 additions and 69 deletions
+20 -13
View File
@@ -42,7 +42,7 @@ export interface IListViewProps<Item, Context>
index: number,
item: Item,
context: ListContext<Context>,
onFocus: (e: React.FocusEvent) => void,
onFocus: (item: Item, e: React.FocusEvent) => void,
) => JSX.Element;
/**
@@ -230,19 +230,26 @@ export function ListView<Item, Context = any>(props: IListViewProps<Item, Contex
virtuosoDomRef.current = element;
}, []);
const getItemComponentInternal = useCallback(
(index: number, item: Item, context: ListContext<Context>): JSX.Element => {
const onFocus = (e: React.FocusEvent): void => {
// If one of the item components has been focused directly, set the focused and tabIndex state
// and stop propagation so the ListViews onFocus doesn't also handle it.
const key = getItemKey(item);
setIsFocused(true);
setTabIndexKey(key);
e.stopPropagation();
};
return getItemComponent(index, item, context, onFocus);
/**
* Focus handler passed to each item component.
* Don't declare inside getItemComponent to avoid re-creating on each render.
*/
const onFocusForGetItemComponent = useCallback(
(item: Item, e: React.FocusEvent) => {
// If one of the item components has been focused directly, set the focused and tabIndex state
// and stop propagation so the ListViews onFocus doesn't also handle it.
const key = getItemKey(item);
setIsFocused(true);
setTabIndexKey(key);
e.stopPropagation();
},
[getItemComponent, getItemKey],
[getItemKey],
);
const getItemComponentInternal = useCallback(
(index: number, item: Item, context: ListContext<Context>): JSX.Element =>
getItemComponent(index, item, context, onFocusForGetItemComponent),
[getItemComponent, onFocusForGetItemComponent],
);
/**
* Handles focus events on the list.