Expo中FlatList首次渲染空白 刷新后重复渲染报key重复如何解决
问题根源
你代码里的问题主要集中在以下几处:
- Firebase Realtime Database 的
on()方法是事件监听回调,不返回Promise,await关键字对它无效,导致你执行数据映射时json还没被赋值,首次渲染无数据 - 没有用
setList更新状态直接修改list数组,React 检测不到状态变更不会触发重渲染,只有手动刷新触发组件重渲染才会显示之前攒的数据 - 调用
SendingData的 useEffect 没有加空依赖数组,组件每次重渲染都会重复执行数据插入逻辑,导致数组里不断塞入重复数据触发key冲突 - 固定3秒结束加载的逻辑不合理,应该在数据处理完成后再关闭加载状态
- FlatList 外层套了多余的 Scroll 组件,会导致滚动异常和性能问题
修正后的完整代码
export const HistoryScreen = () => { const [isLoading, setIsLoading] = useState(true); const [list, setList] = useState([]); const firebaseRef = firebase.database().ref(`Orders/${orderData.firebaseUserId}`); useEffect(() => { // 绑定Firebase数据监听 const listener = firebaseRef.on("value", (snapshot) => { const json = snapshot.val() || {}; const keys = Object.keys(json); // 生成新的列表数据 const newList = keys.map((key) => { const k = json[key]; const appliance = Data.find((app) => app.title === k["Appliance_Name"]); return { id: key, title: k['Appliance_Name'], service: k['Service_Requested'], time: k['Time'], status: k["Status"], image: appliance?.image }; }); // 用setList更新状态,触发重渲染 setList(newList); // 数据处理完成关闭加载状态 setIsLoading(false); }); // 组件卸载时移除监听,避免内存泄漏和重复触发 return () => { firebaseRef.off("value", listener); }; }, []); // 空依赖数组,仅组件挂载时执行一次 return ( <SafeArea> <LinearGradient style={styles.screen} colors={[color.screenBackground.g3, color.screenBackground.g2,color.screenBackground.g2, color.screenBackground.g3]}> {isLoading ? ( <View style={styles.loader}> <ActivityIndicator size="large" color={color.screenBackground.g4} /> </View> ) : ( <View style={styles.screen}> <Appointments>Your Appointments</Appointments> <OrderCard> <FlatList style={styles.list} data={list} renderItem={({ item }) => ( <Item> <View style={styles.view}> <View> <Image source={item.image} resizeMode='contain' style={styles.image}/> </View> <View style={styles.container}> <Title>{item.title}</Title> <Service>Job : {item.service}</Service> <Time>Booking Time : {item.time}</Time> <ID>Appointment ID : {item.id}</ID> </View> </View> <Status>Status : {item.status}</Status> </Item> )} keyExtractor={item => item.id} /> </OrderCard> </View> )} </LinearGradient> </SafeArea> ); }
内容的提问来源于stack exchange,提问作者Deep Togani
相关产品推荐
相关产品推荐

