You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 14:21:01