删除Firestore预订后,如何重新渲染React Native FlatList?
问题描述
我有一个电影预订收藏列表,点击按钮可将预订记录从Firestore数据库中删除。目前点击删除按钮后,必须刷新整个应用才能看到列表变化,希望在onPress操作完成后,FlatList能自动重新渲染。
现有代码
const WatchList = () => { const uid = auth.currentUser.uid; const docRef = doc(db, 'users', uid); const [user, setUser] = useState({}); const [watched, setWatched] = useState(true); const [text, setText] = useState('Watched movies'); const [filteredBookings, setFilteredBookings] = useState(bookings); const bookingsRef = collection(db, "booking"); const [bookings, setBookings] = useState({}); useEffect(() => { getUser(); getBookings(); },[]) const getUser = async () => { const snap = await getDoc(docRef) setUser({user, ...snap.data()}) } const getBookings = async () => { const q = query(bookingsRef, where("users","array-contains",auth.currentUser.uid)); const unsubscribe = onSnapshot(q, (querySnapshot) => { const a = []; querySnapshot.forEach((doc) => { a.push(doc.data()); }); setBookings(querySnapshot.docs); }); } const deleteBooking = async(id) => { try { await deleteDoc(doc(db, 'booking', id)); } catch(e) { console.log(e) } console.log('deleted:' + id) } return ( <View> <View> <Text>{text}</Text> </View> <FlatList data = {filteredBookings} numColumns = {1} renderItem = {({item}) => ( <View> <View> <Text>{item.data().movie}</Text> <Text>{item.data().day} - {item.data().showtime}</Text> </View> <View> <TouchableOpacity onPress = {() => {deleteBooking(item.id)}}> <Text>Delete</Text> </TouchableOpacity> </View> </View> )} /> </View> ) } export default WatchList
解决方案
问题出在以下几点,修改后即可实现自动刷新:
filteredBookings未与bookings联动:初始时filteredBookings依赖bookings,但后续bookings更新时未同步更新filteredBookings,需添加useEffect监听bookings变化。bookings初始状态错误:querySnapshot.docs是数组类型,初始状态应设为[]而非{}。- 未清理
onSnapshot监听:getBookings中创建的unsubscribe函数需在组件卸载时调用,避免内存泄漏。
修改后的完整代码:
const WatchList = () => { const uid = auth.currentUser.uid; const docRef = doc(db, 'users', uid); const [user, setUser] = useState({}); const [watched, setWatched] = useState(true); const [text, setText] = useState('Watched movies'); const [filteredBookings, setFilteredBookings] = useState([]); const bookingsRef = collection(db, "booking"); const [bookings, setBookings] = useState([]); useEffect(() => { getUser(); // 获取unsubscribe函数,组件卸载时清理监听 const unsubscribe = getBookings(); return () => unsubscribe(); },[]) // 监听bookings变化,同步更新filteredBookings useEffect(() => { setFilteredBookings(bookings); }, [bookings]) const getUser = async () => { const snap = await getDoc(docRef); setUser(prev => ({...prev, ...snap.data()})); } const getBookings = () => { const q = query(bookingsRef, where("users","array-contains",auth.currentUser.uid)); // 返回unsubscribe函数供清理使用 return onSnapshot(q, (querySnapshot) => { setBookings(querySnapshot.docs); }); } const deleteBooking = async(id) => { try { await deleteDoc(doc(db, 'booking', id)); } catch(e) { console.log(e); } console.log('deleted:' + id); } return ( <View> <View> <Text>{text}</Text> </View> <FlatList data={filteredBookings} numColumns={1} renderItem={({item}) => ( <View> <View> <Text>{item.data().movie}</Text> <Text>{item.data().day} - {item.data().showtime}</Text> </View> <View> <TouchableOpacity onPress={() => deleteBooking(item.id)}> <Text>Delete</Text> </TouchableOpacity> </View> </View> )} /> </View> ) } export default WatchList
关键修改说明
- 添加依赖
bookings的useEffect,当Firestore数据变化触发bookings更新时,filteredBookings会同步更新,进而触发FlatList重新渲染。 - 将
bookings初始状态改为数组,匹配querySnapshot.docs的数据类型。 - 在组件挂载的
useEffect中返回unsubscribe函数,确保组件卸载时停止Firestore实时监听,避免内存泄漏。 - 优化
setUser写法为函数式更新,避免状态依赖问题。
删除操作完成后,Firestore的onSnapshot会自动检测数据变化并更新bookings,FlatList会自动重新渲染,无需手动刷新应用。
内容的提问来源于stack exchange,提问作者Mihailo
相关产品推荐
相关产品推荐

