FlatList嵌套FlatList/ScrollView时出现TypeError:scrollToIndex未定义
问题:嵌套在FlatList/ScrollView中时,React Native FlatList的scrollToIndex方法为undefined
当将TestClass组件嵌套在FlatList或ScrollView内部时,获取到的FlatList实例的scrollToIndex方法为undefined,调用时触发报错:
TypeError: undefined is not a function (near '...this._scrollRef.scrollTo...')
组件代码
class TestClass extends PureComponent<Props> { private leftFilterFlatListRef = null; private rightFilterFlatListRef = null; private setLeftFilterFlatListRef = ref => { this.leftFilterFlatListRef = ref; }; private setRightFilterFlatListRef = ref => { this.rightFilterFlatListRef = ref; }; private onRightFilterGroupItemTitleClickInner = index => { this.rightFilterFlatListRef && this.rightFilterFlatListRef.scrollToIndex({ animated: true, index, viewPosition: 0 }); }; private onLeftFilterItemClickInner = index => { console.log('======context====' + JSON.stringify(this.rightFilterFlatListRef.scrollToIndex)); // undefined this.rightFilterFlatListRef && this.rightFilterFlatListRef.scrollToIndex({ animated: true, index, viewPosition: 0 }); }; public leftFilterScrollTo = index => { this.leftFilterFlatListRef && this.leftFilterFlatListRef.scrollToIndex({ animated: true, index: index, viewPosition: 1 }); }; public rightFilterScrollTo = index => { this.rightFilterFlatListRef && this.rightFilterFlatListRef.scrollToIndex({ animated: true, index, viewPosition: 0 }); }; private renderLeftFilterItem = () => { return <LeftItemComponent item={item} index={index} onLeftFilterItemClick={this.onLeftFilterItemClickInner} />; }; private renderRightFilterItem = () => { return ( <RightItemComponent index={index} item={item} onRightFilterGroupItemTitleClick={this.onRightFilterGroupItemTitleClickInner} /> ); }; private renderLeftFlatItem = ({ item, index }) => { return this.renderLeftFilterItem(this.props, item, index, this.props.onVisible); }; private renderRightFlatItem = ({ item, index }) => { return this.renderRightFilterItem(this.props, item, index, this.props.onVisible); }; render(): React.ReactNode { const { leftFilterData, rightFilterData } = this.props; const nonNullLeftFilterData = leftFilterData || []; const nonNullRightFilterData = rightFilterData || []; return ( <View> <FlatList data={nonNullLeftFilterData} ref={this.setLeftFilterFlatListRef} renderItem={this.renderLeftFlatItem} /> <FlatList data={nonNullRightFilterData} ref={this.setRightFilterFlatListRef} renderItem={this.renderRightFlatItem} /> </View> ); } }
解决方法
改用createRef()获取实例
函数式ref在嵌套场景下可能无法正确指向FlatList实例,换成createRef()并通过current属性访问实例:import React, { PureComponent, createRef } from 'react'; class TestClass extends PureComponent<Props> { private leftFilterFlatListRef = createRef(); private rightFilterFlatListRef = createRef(); private onRightFilterGroupItemTitleClickInner = index => { this.rightFilterFlatListRef.current?.scrollToIndex({ animated: true, index, viewPosition: 0 }); }; // 其他调用scrollToIndex的方法均改为访问current属性 render(): React.ReactNode { // ... return ( <View> <FlatList data={nonNullLeftFilterData} ref={this.leftFilterFlatListRef} renderItem={this.renderLeftFlatItem} /> <FlatList data={nonNullRightFilterData} ref={this.rightFilterFlatListRef} renderItem={this.renderRightFlatItem} /> </View> ); } }确保组件挂载后再调用滚动方法
在类组件的componentDidMount中验证ref是否正确获取,避免在组件未完成挂载时调用:componentDidMount() { // 打印实例确认是否正确获取 console.log('Right FlatList ref:', this.rightFilterFlatListRef.current); }显式设置FlatList的scrollEnabled属性
当嵌套在外部ScrollView/FlatList中时,可能会影响内部FlatList的滚动状态,显式开启滚动:<FlatList scrollEnabled={true} // 其他属性 />使用原生UIManager调用滚动命令(兼容旧版本RN)
如果是React Native旧版本,ref指向异常时,可通过原生UIManager发送命令:import { findNodeHandle, UIManager } from 'react-native'; private onLeftFilterItemClickInner = index => { const flatListNode = findNodeHandle(this.rightFilterFlatListRef.current); if (flatListNode) { UIManager.dispatchViewManagerCommand( flatListNode, UIManager.FlatList.Commands.scrollToIndex, [true, index, 0] // 参数对应animated, index, viewPosition ); } };
内容的提问来源于stack exchange,提问作者yangshasha
相关产品推荐
相关产品推荐

