Description
When using FlashList v2 inside a nested scroll container (a ScrollView in my case), the list causes an infinite render loop and eventually crashes on specific Android devices (e.g. Oppo, Samsung).
The console logs show:
[WARN] Exceeded max renders without commit.
[ERROR] Error: Maximum update depth exceeded.
Replacing FlashList with a regular FlatList immediately fixes the problem — no re-renders, no warnings, and no crashes.
The issue only appears when FlashList is nested inside another scroll view and only on certain Android devices.
Current behavior
FlashList v2 triggers an infinite render loop on some Android devices (Oppo Find X2 Neo / Reno3 Pro, Samsung models).
The app crashes with Maximum update depth exceeded.
Internal components (ViewHolderInternal, ViewHolderCollection) keep re-rendering with props that are equal by value but different by reference.
The list only has 2 items — no duplicate keys and stable references.
The same component works perfectly on iOS and other Android devices.
Verified with why-did-you-render:
Expected behavior
Not trigger infinite renders when data, keys, and layout props are stable.
Work correctly when nested inside a ScrollView (or at least not crash).
Match the behavior of FlatList, which works correctly in the same setup.
Reproduction
I have a vertical scroll list in my landing page like this:
import { ScrollView } from 'react-native-gesture-handler';
import StatsList from './StatsList'; // your StatsList component
const LandingPage = () => {
return (
<ScrollView>
<StatsList />
</ScrollView>
);
};
Here is my StatsList component:
import { FlashList } from '@shopify/flash-list';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { shallowEqual } from 'react-redux';
import { ThemeName, XStack } from 'tamagui';
import { StatsCard } from '@/components/Common/Cards';
import { StatsData, useStats } from '@/components/LandingPage/Dashboard/hooks';
import { useAppSelector } from '@/store/store';
import { SCREEN_WIDTH } from '@/utils/constants';
const StatsList = () => {
const SPACING = 5;
const CELL_WIDTH = SCREEN_WIDTH * 0.54;
const FULL_SIZE = CELL_WIDTH - SPACING;
const { t } = useTranslation();
const overviewMode = useAppSelector((state) => state.landing.overviewMode, shallowEqual);
const appTheme = useAppSelector((state) => state.settings.theme, shallowEqual);
const data = useStats(overviewMode);
const renderItem = useCallback(
({ item }: { item: StatsData }) => {
const theme = appTheme === 'light' ? ('pastell_beige' as ThemeName) : ('silver' as ThemeName);
return (
<XStack width={CELL_WIDTH} padding={SPACING}>
<StatsCard
hasProgressBar
title={t(item.title)}
value={item.value}
maxValue={item.maxValue}
subTitle={item.subTitle}
subValue={item.subValue}
theme={theme}
brightGradient={appTheme === 'dark'}
/>
</XStack>
);
},
[appTheme, t, CELL_WIDTH]
);
const keyExtractor = useCallback(
(item: StatsData, index: number) => `${overviewMode}-${item.title}-${index}`,
[overviewMode]
);
//Flashlist causes infinite render loop in v2 for android, reverting to FlatList for now since it's small list should be fine
return (
<FlashList
data={data}
keyExtractor={keyExtractor}
horizontal
snapToInterval={FULL_SIZE + SPACING}
showsHorizontalScrollIndicator={false}
decelerationRate="fast"
renderItem={renderItem}
/>
);
};
export default memo(StatsList);
Expo Snack or minimal reproduction link:
https://snack.expo.dev/@rtn95/exceeded-max-renders-without-commit
Platform
Environment
Only happens in production build and mostly on Oppo Devices.
FlashList version: "@shopify/flash-list": "^2.1.0",
"react-native-gesture-handler": "^2.28.0",
Additional context
The issue disappears when switching back to FlatList. I don't get any why-did-you-render logs when using FlatList and tested a production build which does not crash.
The bug seems tied to layout measurement or prop identity within FlashList’s internal components.
The problem only occurs on specific Android devices.
Checklist
Description
When using FlashList v2 inside a nested scroll container (a ScrollView in my case), the list causes an infinite render loop and eventually crashes on specific Android devices (e.g. Oppo, Samsung).
The console logs show:
The issue only appears when FlashList is nested inside another scroll view and only on certain Android devices.
Current behavior
FlashList v2 triggers an infinite render loop on some Android devices (Oppo Find X2 Neo / Reno3 Pro, Samsung models).
The app crashes with Maximum update depth exceeded.
Internal components (ViewHolderInternal, ViewHolderCollection) keep re-rendering with props that are equal by value but different by reference.
The list only has 2 items — no duplicate keys and stable references.
The same component works perfectly on iOS and other Android devices.
Verified with why-did-you-render:
Expected behavior
Not trigger infinite renders when data, keys, and layout props are stable.
Work correctly when nested inside a ScrollView (or at least not crash).
Match the behavior of FlatList, which works correctly in the same setup.
Reproduction
I have a vertical scroll list in my landing page like this:
Here is my StatsList component:
Expo Snack or minimal reproduction link:
https://snack.expo.dev/@rtn95/exceeded-max-renders-without-commit
Platform
Environment
Only happens in production build and mostly on Oppo Devices.
FlashList version: "@shopify/flash-list": "^2.1.0",
"react-native-gesture-handler": "^2.28.0",
Additional context
The issue disappears when switching back to FlatList. I don't get any why-did-you-render logs when using FlatList and tested a production build which does not crash.
The bug seems tied to layout measurement or prop identity within FlashList’s internal components.
The problem only occurs on specific Android devices.
Checklist