From 69543a8aeffc150a6143a8bc9952614e30535ef9 Mon Sep 17 00:00:00 2001 From: Chever John Date: Tue, 30 Jun 2026 02:00:04 +0800 Subject: [PATCH] fix: handle null API response data to prevent infinite loading When API returns {"data": null} for empty lists, accessing .plans on null throws an exception. fetchPlans never reaches setLoading(false), causing the dashboard to spin forever. Added optional chaining, fallback defaults, and try-catch-finally to ensure loading stops. Co-Authored-By: Claude --- src/hooks/useDashboardData.ts | 10 +++++----- src/pages/purchaser/Dashboard.tsx | 21 +++++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/hooks/useDashboardData.ts b/src/hooks/useDashboardData.ts index bd5e989..ce25eb9 100644 --- a/src/hooks/useDashboardData.ts +++ b/src/hooks/useDashboardData.ts @@ -47,11 +47,11 @@ export function useDashboardData({ purchaserApi.dashboardStats(), purchaserApi.listPlans(), ]); - const plans = plansRes.data.plans as unknown as T[]; + const plans = (plansRes.data?.plans || []) as unknown as T[]; const stats: DashboardStats = { - all: statsData.total_plans, - producing: statsData.producing_plans, - completed: statsData.completed_plans, + all: statsData.total_plans ?? 0, + producing: statsData.producing_plans ?? 0, + completed: statsData.completed_plans ?? 0, }; return { plans, stats, rejectedPlanIds: new Set() }; }, []); @@ -61,7 +61,7 @@ export function useDashboardData({ textileApi.dashboardStats(), textileApi.listPlans(), ]); - const plans = plansRes.data as unknown as T[]; + const plans = (plansRes.data || []) as unknown as T[]; const stats: DashboardStats = { all: statsData.total_plans, producing: statsData.producing_plans, diff --git a/src/pages/purchaser/Dashboard.tsx b/src/pages/purchaser/Dashboard.tsx index 02ad8fb..1d92c3f 100644 --- a/src/pages/purchaser/Dashboard.tsx +++ b/src/pages/purchaser/Dashboard.tsx @@ -87,15 +87,20 @@ export function PurchaserDashboard() { }, [auth.company, dataLoaded, plans.length]); const fetchPlans = async () => { - const res = await purchaserApi.listPlans(); - const allPlans = res.data.plans; + try { + const res = await purchaserApi.listPlans(); + const allPlans = res.data?.plans || []; - const filteredPlans = allPlans.filter(p => - !p.process_steps?.some(s => s.status === STEP_STATUS.REJECTED) - ); - setPlans(filteredPlans); - setLoading(false); - setDataLoaded(true); + const filteredPlans = allPlans.filter(p => + !p.process_steps?.some(s => s.status === STEP_STATUS.REJECTED) + ); + setPlans(filteredPlans); + } catch (err) { + console.error('Failed to fetch plans:', err); + } finally { + setLoading(false); + setDataLoaded(true); + } }; // 监听页面可见性变化,返回页面时刷新数据