首次加载屏幕时,React Native FlatList scrollToIndex() 不起作用
React Native FlatList scrollToIndex() is not working when screen loaded for the first time
我的 React Native 应用程序中有这个类别过滤器组件。第一次加载此组件时,它不会滚动到给定的索引项(即 3)。我检查了一下,函数 scrollToIndex
正在调用。但是当组件重新渲染时加载屏幕后它正在工作。
为什么第一次加载屏幕时不向下滚动?
import React, { useCallback, useRef } from 'react'
import { StyleSheet, TouchableOpacity, FlatList, View } from 'react-native'
import { Badge, Text } from 'native-base'
import { connect } from 'react-redux'
import * as categoryActions from '../../Redux/Actions/categoryActions'
import { useFocusEffect } from '@react-navigation/native'
const CategoryFilter = (props) => {
const flatlistRef = useRef()
const handleSetSelectedCategoryId = (categoryId) => {
props.setSelectedCategoryId(categoryId)
}
const getItemLayout = (data, index) => ({
length: 50,
offset: 50 * index,
index,
})
const scrollToIndex = () => {
console.log('scroll to index called !')
let index = 3
flatlistRef.current.scrollToIndex({ animated: true, index: index })
}
useFocusEffect(
useCallback(() => {
scrollToIndex()
}, [])
)
const renderItem = ({ item, index }) => {
return (
<TouchableOpacity
key={item._id}
onPress={() => {
handleSetSelectedCategoryId(item._id)
}}
>
<Badge
style={[
styles.center,
{ margin: 5, flexDirection: 'row' },
item._id == props.selectedCategoryId
? styles.active
: styles.inactive,
]}
>
<Text style={{ color: 'white' }}>{item.name}</Text>
</Badge>
</TouchableOpacity>
)
}
return (
<View>
<FlatList
data={props.categories}
renderItem={renderItem}
keyExtractor={(item) => item._id}
horizontal={true}
ref={flatlistRef}
getItemLayout={getItemLayout}
/>
</View>
)
}
....
我遇到了类似的问题,这些是我的发现:
似乎在 flatlist 使用 getItemLayout 完成计算项目大小之前发生 scrollToIndex 的竞争条件。所以它不会抛出超出范围的错误并认为滚动成功。
一个解决方案是:
setTimeout(() => scrollToIndex(), 500);
然而,这不是一个很好的解决方案,因为不能保证平面列表 'ready' 在任意给定的 500 毫秒内滚动,这意味着我们的延迟调用仍然无法正常工作。
推荐方式:
在 FlatList 上设置 initialScrollIndex
我们要滚动到的索引。
数据数组(传递给 FlatList)需要已经有您要查找的索引,否则会出现超出范围的错误。
您还应该注意(来自文档):
This disables the "scroll to top" optimization that keeps the first initialNumToRender items always rendered and immediately renders the items starting at this initial index.
更多信息在这里:https://reactnative.dev/docs/flatlist#initialscrollindex
对于初始渲染,最好使用 initialScrollIndex 而不是 scrollToIndex,此外还必须使用 getItemLayout,如下所示:
const getItemLayout = (data, index) => {
return{
长度:屏幕宽度,
偏移量:屏幕宽度 * 索引,
指数,
};
};
从 react natie 的 dimensions prop 获取屏幕宽度
我的 React Native 应用程序中有这个类别过滤器组件。第一次加载此组件时,它不会滚动到给定的索引项(即 3)。我检查了一下,函数 scrollToIndex
正在调用。但是当组件重新渲染时加载屏幕后它正在工作。
为什么第一次加载屏幕时不向下滚动?
import React, { useCallback, useRef } from 'react'
import { StyleSheet, TouchableOpacity, FlatList, View } from 'react-native'
import { Badge, Text } from 'native-base'
import { connect } from 'react-redux'
import * as categoryActions from '../../Redux/Actions/categoryActions'
import { useFocusEffect } from '@react-navigation/native'
const CategoryFilter = (props) => {
const flatlistRef = useRef()
const handleSetSelectedCategoryId = (categoryId) => {
props.setSelectedCategoryId(categoryId)
}
const getItemLayout = (data, index) => ({
length: 50,
offset: 50 * index,
index,
})
const scrollToIndex = () => {
console.log('scroll to index called !')
let index = 3
flatlistRef.current.scrollToIndex({ animated: true, index: index })
}
useFocusEffect(
useCallback(() => {
scrollToIndex()
}, [])
)
const renderItem = ({ item, index }) => {
return (
<TouchableOpacity
key={item._id}
onPress={() => {
handleSetSelectedCategoryId(item._id)
}}
>
<Badge
style={[
styles.center,
{ margin: 5, flexDirection: 'row' },
item._id == props.selectedCategoryId
? styles.active
: styles.inactive,
]}
>
<Text style={{ color: 'white' }}>{item.name}</Text>
</Badge>
</TouchableOpacity>
)
}
return (
<View>
<FlatList
data={props.categories}
renderItem={renderItem}
keyExtractor={(item) => item._id}
horizontal={true}
ref={flatlistRef}
getItemLayout={getItemLayout}
/>
</View>
)
}
....
我遇到了类似的问题,这些是我的发现:
似乎在 flatlist 使用 getItemLayout 完成计算项目大小之前发生 scrollToIndex 的竞争条件。所以它不会抛出超出范围的错误并认为滚动成功。
一个解决方案是:
setTimeout(() => scrollToIndex(), 500);
然而,这不是一个很好的解决方案,因为不能保证平面列表 'ready' 在任意给定的 500 毫秒内滚动,这意味着我们的延迟调用仍然无法正常工作。
推荐方式:
在 FlatList 上设置 initialScrollIndex
我们要滚动到的索引。
数据数组(传递给 FlatList)需要已经有您要查找的索引,否则会出现超出范围的错误。
您还应该注意(来自文档):
This disables the "scroll to top" optimization that keeps the first initialNumToRender items always rendered and immediately renders the items starting at this initial index.
更多信息在这里:https://reactnative.dev/docs/flatlist#initialscrollindex
对于初始渲染,最好使用 initialScrollIndex 而不是 scrollToIndex,此外还必须使用 getItemLayout,如下所示:
const getItemLayout = (data, index) => { return{ 长度:屏幕宽度, 偏移量:屏幕宽度 * 索引, 指数, }; };
从 react natie 的 dimensions prop 获取屏幕宽度