React Native中如何将FlatList数据传递给BottomSheet?
核心思路
不需要为每个列表项创建独立的BottomSheet,只需维护一个共享的BottomSheet实例,通过状态管理当前选中的列表项数据,点击按钮时更新状态并触发BottomSheet打开即可,这样能大幅提升性能。
修改后的完整代码
import { BottomSheetModal, BottomSheetModalProvider, BottomSheetScrollView } from '@gorhom/bottom-sheet'; import { useRef, useState, useCallback, useMemo } from "react"; import { View, FlatList, Text, TouchableOpacity } from 'react-native'; // 模拟自定义AppButton组件,实际替换为你的按钮组件即可 const AppButton = ({ title, style, onPress }) => ( <TouchableOpacity style={[{ padding: 10, backgroundColor: '#eee', borderRadius: 8 }, style]} onPress={onPress}> <Text>{title}</Text> </TouchableOpacity> ); const DATA = [ { id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba', title: 'John Doe', }, { id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63', title: 'John Smith', }, { id: '58694a0f-3da1-471f-bd96-145571e29d72', title: 'John Lennon', }, ]; const Item = ({ title, onPress }) => ( <AppButton title={title} style={{ marginVertical: 10 }} onPress={onPress} /> ); const App = () => { // 获取BottomSheetModal实例,用于调用打开/关闭方法 const bottomSheetModalRef = useRef(null); // 存储当前选中的列表项数据 const [selectedItem, setSelectedItem] = useState(null); // 缓存BottomSheet停靠点,避免每次渲染重新创建数组 const snapPoints = useMemo(() => ['25%', '50%'], []); // 缓存打开BottomSheet的函数,减少不必要的重渲染 const handlePresentModalPress = useCallback(() => { bottomSheetModalRef.current?.present(); }, []); // 处理列表项点击:先设置选中数据,再打开BottomSheet const handleItemPress = useCallback((item) => { setSelectedItem(item); handlePresentModalPress(); }, [handlePresentModalPress]); const handleSheetChanges = useCallback((index) => { console.log('BottomSheet状态变化:', index); }, []); return ( <BottomSheetModalProvider> <View style={{ flex: 1, padding: 20 }}> <FlatList data={DATA} keyExtractor={item => item.id} renderItem={({ item }) => <Item title={item.title} onPress={() => handleItemPress(item)} />} /> </View> <BottomSheetModal ref={bottomSheetModalRef} index={0} snapPoints={snapPoints} enablePanDownToClose onChange={handleSheetChanges} > <BottomSheetScrollView style={{ padding: 20 }}> {/* 展示选中的列表项数据 */} {selectedItem && ( <Text>当前选中:{selectedItem.title}</Text> )} </BottomSheetScrollView> </BottomSheetModal> </BottomSheetModalProvider> ) } export default App;
关键部分解释
BottomSheetModalProvider层级修正
必须将所有使用BottomSheet的组件(包括FlatList)包裹在BottomSheetModalProvider内部,否则BottomSheet无法正常工作,原代码中Provider与View同级的写法是错误的。useRef的作用
bottomSheetModalRef用来存储BottomSheetModal的实例,通过current属性可以调用组件内置的present()、dismiss()等方法。ref的特性是跨组件渲染周期保存引用,不会因组件重新渲染丢失实例,这是复用同一个BottomSheet的核心。useCallback的作用
用useCallback包裹handlePresentModalPress和handleItemPress,是为了缓存函数引用,避免组件每次重新渲染时创建新的函数实例。这样能减少FlatList子组件的不必要重渲染,提升性能。状态管理选中数据
通过useState创建selectedItem状态,点击列表项时先更新该状态,再打开BottomSheet,确保BottomSheet能获取并展示当前选中项的数据。复用BottomSheet的优势
仅维护一个BottomSheet实例,相比为每个列表项创建独立的BottomSheet,能大幅减少内存占用和组件初始化开销,数据量越大,性能提升越明显。
内容的提问来源于stack exchange,提问作者serking

