Skip to content

Commit

Permalink
Fix remount of SectionList header and footer (#42080)
Browse files Browse the repository at this point in the history
Summary:
By default SectionList overrides `stickyHeaderIndices` with generated array based on `sections` provided via props. With this changes list header and footer keeps mounted when sections prop is changing from empty list to filled list and vice versa.

## Changelog:

[General] [Fixed] - Fix remount of header and footer in `SectionList` while transiting between empty and filled state

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests

Pull Request resolved: #42080

Test Plan:
**Before:**
https://github.com/facebook/react-native/assets/16048381/18d31bc2-817e-4a8d-88a8-0ad19fc71816
**After:**
https://github.com/facebook/react-native/assets/16048381/e205faad-7d55-4f96-a866-56e5eca976b6

**Playground:**
https://snack.expo.dev/Ypb-SSHVz?platform=android

## Knowledge base
https://www.smashingmagazine.com/2021/08/react-children-iteration-methods/

Reviewed By: NickGerleman

Differential Revision: D52508916

Pulled By: cipolleschi

fbshipit-source-id: 430463261887e9551f10c5c2dae352e0060ad6c4
  • Loading branch information
MateWW authored and facebook-github-bot committed Jan 5, 2024
1 parent d50c906 commit 0c37f8c
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1668,13 +1668,14 @@ class ScrollView extends React.Component<Props, State> {

const {stickyHeaderIndices} = this.props;
let children = this.props.children;
/**
* This function can cause unnecessary remount when nested in conditionals as it causes remap of children keys.
* https://react.dev/reference/react/Children#children-toarray-caveats
*/
children = React.Children.toArray<$FlowFixMe>(children);

if (stickyHeaderIndices != null && stickyHeaderIndices.length > 0) {
const childArray = React.Children.toArray<$FlowFixMe>(
this.props.children,
);

children = childArray.map((child, index) => {
children = children.map((child, index) => {
const indexOfIndex = child ? stickyHeaderIndices.indexOf(index) : -1;
if (indexOfIndex > -1) {
const key = child.key;
Expand All @@ -1686,7 +1687,7 @@ class ScrollView extends React.Component<Props, State> {
key={key}
ref={ref => this._setStickyHeaderRef(key, ref)}
nextHeaderLayoutY={this._headerLayoutYs.get(
this._getKeyForIndex(nextIndex, childArray),
this._getKeyForIndex(nextIndex, children),
)}
onLayout={event => this._onStickyHeaderLayout(index, event, key)}
scrollAnimatedValue={this._scrollAnimatedValue}
Expand Down
7 changes: 6 additions & 1 deletion packages/react-native/Libraries/Lists/SectionList.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,13 @@ export type SectionListRenderItem<ItemT, SectionT = DefaultSectionT> = (
info: SectionListRenderItemInfo<ItemT, SectionT>,
) => React.ReactElement | null;

type VirtualizedListWithoutPreConfiguredProps<ItemT> = Omit<
VirtualizedListWithoutRenderItemProps<ItemT>,
'stickyHeaderIndices'
>;

export interface SectionListProps<ItemT, SectionT = DefaultSectionT>
extends VirtualizedListWithoutRenderItemProps<ItemT> {
extends VirtualizedListWithoutPreConfiguredProps<ItemT> {
/**
* Rendered in between each section.
*/
Expand Down

0 comments on commit 0c37f8c

Please sign in to comment.