react / react/react-native

SectionList - maintainVisibleContentPosition not working as expected.

Open
#30,775 10 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug Component: SectionList Never gets stale Platform: Android
Dominant language
C++
Stars
127k
Forks
25.3k
Avg merge
1d 23h
Merged PRs (30d)
4

Description

Description

I am implementing a bidirectional chat. When prepending bubble messages to my sectionlist, the look-and-feel is not smoothy, the scroll position is auto-scrolled to the top. In other words, the new content inserted at the top is moving down the current visible content.

Testing on iPhone 11 pro, iOS 14.3

React Native version:

System:
OS: Windows 10 10.0.19041
CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
Memory: 8.07 GB / 15.85 GB
Binaries:
Node: 12.18.1 - C:\Program Files\nodejs\node.EXE
Yarn: 1.22.4 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
npm: 6.14.5 - C:\Program Files\nodejs\npm.CMD
Watchman: Not Found
SDKs:
Android SDK: Not Found
Windows SDK: Not Found
IDEs:
Android Studio: Version 3.6.0.0 AI-192.7142.36.36.6241897
Visual Studio: Not Found
Languages:
Java: 1.8.0_221
Python: 3.7.4
npmPackages:
@react-native-community/cli: Not Found
react: ^16.13.1 => 16.14.0
react-native: ^0.63.4 => 0.63.4
react-native-windows: ^0.63.16 => 0.63.16

Steps To Reproduce

Provide a detailed list of steps that reproduce the issue.

  1. Create a bidirectional SectionList with pagination.
  2. Prepend 20 items to it when top reached.

const keyExtractor = useCallback(({ id }) => id, []);

const renderItem = useCallback(({ item, index }) => {
  const { content, date, mine } = item;

  const { onBubbleLongPress } = props;

  return (
    <View
      onLayout={(event) => {
        itemHeights.current[index] = event.nativeEvent.layout.height;
      }}
    >
      <Bubble
        content={content}
        date={date}
        mine={mine}
        onLongPress={() => onBubbleLongPress?.(item)}
      />
    </View>
  );
}, []);


const handleOnScroll = ({ nativeEvent }) => {
  if (isScrollCloseToTop(nativeEvent)) {
    props.onStartReached?.();
  }
};

const isScrollCloseToTop = ({ contentOffset, contentSize }) => {
   const currentYOffset = contentOffset.y;
   const diff = currentYOffset - lastYOffset.current;
   lastYOffset.current = contentOffset.y;
   // Close to top when scrolling to the top and distance is <= 30% content's height
   return diff < 0 && contentOffset.y <= 0.3 * contentSize.height;
};

return (
   <SectionList
      sections={sections}
      keyExtractor={keyExtractor}
      renderItem={renderItem}
      renderSectionHeader={renderSectionHeader}
      onScroll={handleOnScroll}
      maintainVisibleContentPosition={{
        minIndexForVisible: 0,
      }}
  />
);

      

Expected Results

New content not moving down the current visible content.

Snack, code example, screenshot, or link to a repository:

I am getting the same behaviour of this snack https://snack.expo.io/@rainliu123/flatlisttest

Note: not only for the first prepend. For all of them.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the SectionList reproduction described in the issue and run the linked Expo Snack. Reproduce the bidirectional list by prepending 20 items with maintainVisibleContentPosition set to minIndexForVisible: 0, then compare the observed scroll movement with the expected result that visible content does not move. The issue does not identify a source file or test.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, react-native
Domain
mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.