react / react/react-native

SectionList scrollToLocation does not scroll to the correct position

Open
#55,013 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Component: SectionList Needs: Triage :mag:
Dominant language
C++
Stars
127k
Forks
25.3k
Avg merge
1d 23h
Merged PRs (30d)
4

Description

Description

When a SectionList contains a large number of items, calling scrollToLocation
scrolls to a slightly incorrect position, even though getItemLayout is properly provided.

Instead of scrolling exactly to the specified item, the list stops a bit offset from the expected location.

If this behavior is expected or if my usage of SectionList / getItemLayout is incorrect,
I would appreciate any guidance on the correct approach.

import React, { useRef, useMemo } from 'react';
import { SectionList, Text, View, Button } from 'react-native';

const HEADER_HEIGHT = 40;
const ITEM_HEIGHT = 30;

const TARGET_SECTION_INDEX = 20;

const generateSections = () => {
  const createItems = (prefix) => {
    const count = 20 + Math.floor(Math.random() * 100);
    return [...Array(count)].map((_, i) => ({
      label: `${prefix} Item ${i + 1}`,
    }));
  };

  return [...Array(24)].map((_, sectionIndex) => ({
    title: `Section ${sectionIndex + 1}`,
    data: createItems(`Section ${sectionIndex + 1}`),
  }));
};

export default function App() {
  const sectionListRef = useRef(null);
  const sections = useMemo(() => generateSections(), []);

  const scrollToSection = () => {
    if (sectionListRef.current) {
      sectionListRef.current.scrollToLocation({
        sectionIndex: TARGET_SECTION_INDEX,
        itemIndex: 0,
        viewPosition: 0,
      });
    }
  };

  return (
    <View style={{ flex: 1, paddingTop: 40 }}>
      <Button
        title={`Scroll to Section ${TARGET_SECTION_INDEX + 1}`}
        onPress={scrollToSection}
      />
      <SectionList
        ref={sectionListRef}
        sections={sections}
        keyExtractor={(item, index) => item.label + index}
        renderItem={({ item }) => (
          <View
            style={{
              height: ITEM_HEIGHT,
              justifyContent: 'center',
              borderBottomWidth: 1,
              borderColor: '#ccc',
            }}>
            <Text>{item.label}</Text>
          </View>
        )}
        renderSectionHeader={({ section: { title } }) => (
          <View
            style={{
              justifyContent: 'center',
              height: HEADER_HEIGHT,
              backgroundColor: '#eee',
            }}>
            <Text
              style={{
                fontWeight: 'bold',
              }}>
              {title}
            </Text>
          </View>
        )}
        getItemLayout={(_, index) => ({
          index,
          length: ITEM_HEIGHT,
          offset: ITEM_HEIGHT * index,
        })}
      />
    </View>
  );
}

Steps to reproduce
  1. Render a SectionList
  2. Call scrollToLocation with a valid sectionIndex and itemIndex
  3. Observe the scroll position
React Native Version

0.81.4

Affected Platforms

Other (please specify), Runtime - Android

Output of npx @react-native-community/cli info
skip
Stacktrace or Logs
nothing
MANDATORY Reproducer

https://snack.expo.dev/@kuroppi/sectionlist-scrolltolocation

Screenshots and Videos

expected:
Image

actual:
Image

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

Run the linked Snack reproducer on Android and compare SectionList.scrollToLocation with the supplied getItemLayout behavior. Start by tracing the SectionList scrollToLocation entry point and the handling of sectionIndex and itemIndex. Done means the requested section and item reach the expected position for large lists.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.