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

React useEffect中数据过滤的刷新异常问题排查

React组件数据加载时序问题分析与解决

问题场景

本地开发时组件首次加载数据正常,但部署到线上环境后出现加载错误;本地刷新页面时,控制台会先打印正确的id和空数组,之后才会加载到完整数据。

组件原代码

const { id } = useParams();
const { tripData, facilityData } = useContext(AppContext);
const [data, setData] = useState([]);

useEffect(() => {
    const idResults = facilityData.filter(facility => facility.id === id);

    if (idResults.length > 0) {
        setData(idResults[0]);
    }
}, [])

变量说明

  • [data, setData]:用于填充页面容器的状态
  • facilityData:从AppContext中获取的数据集
  • id:从URL参数中提取的目标资源ID

排查时修改的代码

const { id } = useParams();
const { tripData, facilityData } = useContext(AppContext);
const [data, setData] = useState([]);

useEffect(() => {
    const idResults = facilityData.filter(facility => facility.id === id);

    if (idResults.length > 0) {
        setData(idResults[0]);
    } else if (idResults.length === 0) {
        console.log(`id: ${id}`)
        console.log(`len: ${idResults}`)
    }
}, [])

App.js中Firebase数据获取代码

import { collection, getDocs } from "firebase/firestore";
import { db } from "./firebase";
const [truckData, setTruckData] = useState([]);
const [facilityData, setFacilityData] = useState([]);
const [tripData, setTripData] = useState([]);


 useEffect(() => {
    const fetchData = async (resource, setter) => {
        let list = [];

        try {
            const querySnapshot = await getDocs(collection(db, resource));
            querySnapshot.forEach((doc) => {
                let docData = doc.data();

                if (resource === "trips") {
                    docData.startDate = docData.startDate.toDate();
                    docData.endDate = docData.endDate.toDate();
                }

                list.push({ id: doc.id, ...docData });
            });

            setter(list);
        } catch (error) {
            console.log(error);
        }
    };

    fetchData("trucks", setTruckData);
    fetchData("facilities", setFacilityData);
    fetchData("trips", setTripData);
}, []);

现象原因

  1. 时序不匹配:组件的useEffect依赖为空数组,仅在组件挂载时执行一次。此时AppContext中的facilityData还是初始空数组(Firebase异步请求尚未完成),所以过滤后得到空结果,控制台打印空数组。
  2. 环境差异:本地开发环境中,数据加载完成后组件会自动重新渲染,后续能获取到正确数据;但线上托管服务可能因缓存策略、资源加载顺序或网络延迟,导致组件未重新触发数据匹配逻辑,最终出现错误。

解决方案

1. 修正useEffect依赖项

给组件的useEffect添加id和facilityData作为依赖,确保当URL参数变化或数据集更新时,重新执行过滤逻辑:

const { id } = useParams();
const { tripData, facilityData } = useContext(AppContext);
const [data, setData] = useState([]);

useEffect(() => {
    const idResults = facilityData.filter(facility => facility.id === id);

    if (idResults.length > 0) {
        setData(idResults[0]);
    } else {
        console.log(`id: ${id}`)
        console.log(`len: ${idResults.length}`)
    }
}, [id, facilityData]) // 添加依赖项

2. 添加加载状态提示

在组件中判断facilityData是否为空,显示加载提示提升用户体验:

if (!facilityData.length) {
    return <div>加载中...</div>;
}

// 后续渲染逻辑

3. 优化数据获取逻辑

在App.js中使用Promise.all等待所有数据请求完成后再更新状态,避免子组件拿到不完整的数据集:

useEffect(() => {
    const fetchData = async (resource) => {
        let list = [];
        try {
            const querySnapshot = await getDocs(collection(db, resource));
            querySnapshot.forEach((doc) => {
                let docData = doc.data();
                if (resource === "trips") {
                    docData.startDate = docData.startDate.toDate();
                    docData.endDate = docData.endDate.toDate();
                }
                list.push({ id: doc.id, ...docData });
            });
            return list;
        } catch (error) {
            console.log(error);
            return [];
        }
    };

    const loadAllData = async () => {
        const [trucks, facilities, trips] = await Promise.all([
            fetchData("trucks"),
            fetchData("facilities"),
            fetchData("trips")
        ]);
        setTruckData(trucks);
        setFacilityData(facilities);
        setTripData(trips);
    };

    loadAllData();
}, []);

最终排查结果

经过详细排查,问题并非出自项目代码本身,而是由托管服务的配置或特性导致。

内容的提问来源于stack exchange,提问作者jwald3

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 09:24:18