perf(hooks): 使用 useRef 缓存加载状态,避免 Tab 切换重复请求
- 使用 useRef 替代 useState 跟踪 hasLoaded 状态 - Tab 切换回来时保持数据缓存,不重新发起请求 - stockCode 变化时重置加载状态,确保新股票正常加载 - useAnnouncementsData 支持 refreshKey 强制刷新 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// src/views/Company/components/CompanyOverview/hooks/useShareholderData.ts
|
||||
// 股权结构数据 Hook - 用于股权结构 Tab
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { logger } from "@utils/logger";
|
||||
import axios from "@utils/axiosConfig";
|
||||
import type { ActualControl, Concentration, Shareholder } from "../types";
|
||||
@@ -42,7 +42,10 @@ export const useShareholderData = (options: UseShareholderDataOptions): UseShare
|
||||
const [topCirculationShareholders, setTopCirculationShareholders] = useState<Shareholder[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [hasLoaded, setHasLoaded] = useState(false);
|
||||
// 使用 ref 跟踪是否已加载,避免 Tab 切换时重复请求
|
||||
const hasLoadedRef = useRef(false);
|
||||
// 记录上次加载的 stockCode,stockCode 变化时需要重新加载
|
||||
const lastStockCodeRef = useRef<string | undefined>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
// 只有 enabled 且有 stockCode 时才请求
|
||||
@@ -51,6 +54,18 @@ export const useShareholderData = (options: UseShareholderDataOptions): UseShare
|
||||
return;
|
||||
}
|
||||
|
||||
// stockCode 变化时重置加载状态
|
||||
if (lastStockCodeRef.current !== stockCode) {
|
||||
hasLoadedRef.current = false;
|
||||
lastStockCodeRef.current = stockCode;
|
||||
}
|
||||
|
||||
// 如果已经加载过数据,不再重新请求(Tab 切换回来时保持缓存)
|
||||
if (hasLoadedRef.current) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const controller = new AbortController();
|
||||
|
||||
const loadData = async () => {
|
||||
@@ -75,7 +90,7 @@ export const useShareholderData = (options: UseShareholderDataOptions): UseShare
|
||||
if (shareholdersRes.success) setTopShareholders(shareholdersRes.data);
|
||||
if (circulationRes.success) setTopCirculationShareholders(circulationRes.data);
|
||||
setLoading(false);
|
||||
setHasLoaded(true);
|
||||
hasLoadedRef.current = true;
|
||||
} catch (err: any) {
|
||||
// 请求被取消时,不更新任何状态
|
||||
if (err.name === "CanceledError") {
|
||||
@@ -84,7 +99,7 @@ export const useShareholderData = (options: UseShareholderDataOptions): UseShare
|
||||
logger.error("useShareholderData", "loadData", err, { stockCode });
|
||||
setError("加载股权结构数据失败");
|
||||
setLoading(false);
|
||||
setHasLoaded(true);
|
||||
hasLoadedRef.current = true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -92,7 +107,7 @@ export const useShareholderData = (options: UseShareholderDataOptions): UseShare
|
||||
return () => controller.abort();
|
||||
}, [stockCode, enabled]);
|
||||
|
||||
const isLoading = loading || (enabled && !hasLoaded && !error);
|
||||
const isLoading = loading || (enabled && !hasLoadedRef.current && !error);
|
||||
|
||||
return {
|
||||
actualControl,
|
||||
|
||||
Reference in New Issue
Block a user