The best solution without having to scroll to the center I found is using array like object with very big length and use it as data.
const loopedData = {length: 100000} as undefined[]; // created outside component
const initialIndex = originalData
? Math.round(loopedData.length / 2 - originalData.length / 2)
: 0;
<FlatList
...
data={originalData ? loopedData : null}
extraData={originalData}
initialScrollIndex={initialIndex}
getItemLayout={getItemLayout}
...
/>
But in render take data from original array:
const render = (info: ListRenderItemInfo<undefined>) => {
if (!originalData) return null;
const originalItemIndex = getOriginalItemIndex(
info.index,
originalData.length,
initialIndex,
);
return renderItemImpl?.({
index: originalItemIndex,
item: originalData[originalItemIndex],
separators: info.separators,
});
}
Here are some helpers for implementing this approach:
export const getOriginalItemIndex = (
index: number,
originalLength: number,
initialScrollIndex: number,
) => {
return (
(index + originalLength - (initialScrollIndex % originalLength)) %
originalLength
);
};
// used for scrolling to nearest index
export const getNearestToCurrentIndex = (
currentIndex: number,
originalIndex: number,
originalIndexTo: number,
originalLength: number,
) => {
if (originalIndex === originalIndexTo) return currentIndex;
const rightDistance =
originalIndexTo > originalIndex
? originalIndexTo - originalIndex
: originalLength - originalIndex + originalIndexTo;
const leftDistance = originalLength - rightDistance;
const result =
rightDistance <= leftDistance
? currentIndex + rightDistance
: currentIndex - leftDistance;
return result;
};
You can also recenter list when screen disappears but not unmounted, but not necessary.