Flatlist触发onEndReached更新state时自动滚动至顶部问题
问题原因与解决方案
核心问题:FlatList 因组件重复挂载丢失滚动位置
当你触发onEndReached调用setPage更新状态时,Order组件会重渲染,此时renderScenes里的场景渲染函数(比如pending: () => <Pending .../>)会被重新创建,导致TabView认为这是一个全新的组件,会卸载旧的Pending组件并挂载新的实例——这直接导致FlatList重置到顶部,因为新挂载的FlatList没有保存之前的滚动状态。
具体修复步骤
- 稳定场景渲染函数的引用
用useCallback包裹每个场景的渲染函数,确保组件重渲染时函数引用不变,避免TabView重复卸载/挂载子组件:
const Order = ({navigation}: any) => { // ... 其他状态和函数 // 用useCallback包裹场景渲染函数 const renderPending = useCallback(() => ( <Pending loading={loading} orderData={orderData} onEndReached={handleEndReached} /> ), [loading, orderData, handleEndReached]); const renderConfirmed = useCallback(() => ( <Confirmed loading={loading} orderData={orderData} /> ), [loading, orderData]); const renderAll = useCallback(() => ( <All loading={loading} orderData={orderData} /> ), [loading, orderData]); const renderScenes = { pending: renderPending, confirmed: renderConfirmed, all: renderAll, }; // ... 其他代码 };
- 优化keyExtractor(可选但推荐)
当前keyExtractor使用${item.id}-${index},如果分页加载时数据追加,index会变化,可能导致FlatList重新渲染部分项。建议直接用唯一的item.id作为key:
keyExtractor={(item) => item.id.toString()}
- 避免不必要的组件重渲染(可选)
给Pending、Confirmed、All组件添加React.memo,减少不必要的重渲染:
const Pending = React.memo(({orderData, loading, onEndReached}: any) => { // 组件原有代码 });
补充说明
即使你还没调用API,setPage触发的组件重渲染已经足够让场景组件重新挂载,这就是滚动到顶部的根本原因。通过稳定组件引用,就能保留FlatList的滚动状态。
内容的提问来源于stack exchange,提问作者Anand Kumar
相关产品推荐
相关产品推荐

