From 06dc7a6ef40627142638233619bdbafb22ff858b Mon Sep 17 00:00:00 2001 From: Slinetrac Date: Tue, 14 Oct 2025 21:57:33 +0800 Subject: [PATCH] refactor: home components --- src/components/home/clash-mode-card.tsx | 2 +- .../home/enhanced-canvas-traffic-graph.tsx | 43 +++++++----- .../home/enhanced-traffic-stats.tsx | 2 +- src/components/home/system-info-card.tsx | 70 +++++++++++++------ 4 files changed, 79 insertions(+), 38 deletions(-) diff --git a/src/components/home/clash-mode-card.tsx b/src/components/home/clash-mode-card.tsx index 9458da05..10c56fb7 100644 --- a/src/components/home/clash-mode-card.tsx +++ b/src/components/home/clash-mode-card.tsx @@ -31,7 +31,7 @@ export const ClashModeCard = () => { ); } return t("Core communication error"); - }, [currentMode]); + }, [currentMode, t]); // 模式图标映射 const modeIcons = useMemo( diff --git a/src/components/home/enhanced-canvas-traffic-graph.tsx b/src/components/home/enhanced-canvas-traffic-graph.tsx index 7f78cf66..8e59c4d1 100644 --- a/src/components/home/enhanced-canvas-traffic-graph.tsx +++ b/src/components/home/enhanced-canvas-traffic-graph.tsx @@ -6,6 +6,7 @@ import { useEffect, useImperativeHandle, useMemo, + useReducer, useRef, useState, } from "react"; @@ -80,6 +81,11 @@ interface EnhancedCanvasTrafficGraphProps { ref?: Ref; } +const displayDataReducer = ( + _: ITrafficDataPoint[], + payload: ITrafficDataPoint[], +): ITrafficDataPoint[] => payload; + /** * 稳定版Canvas流量图表组件 * 修复闪烁问题,添加时间轴显示 @@ -118,7 +124,11 @@ export const EnhancedCanvasTrafficGraph = memo( const isInitializedRef = useRef(false); // 当前显示的数据缓存 - const [displayData, setDisplayData] = useState([]); + const [displayData, dispatchDisplayData] = useReducer( + displayDataReducer, + [], + ); + const debounceTimeoutRef = useRef(null); // 主题颜色配置 const colors = useMemo( @@ -133,26 +143,27 @@ export const EnhancedCanvasTrafficGraph = memo( ); // 更新显示数据(防抖处理) - const updateDisplayDataDebounced = useMemo(() => { - let timeoutId: number; - return (newData: ITrafficDataPoint[]) => { - clearTimeout(timeoutId); - timeoutId = window.setTimeout(() => { - setDisplayData(newData); - }, 50); // 50ms防抖 - }; + const updateDisplayData = useCallback((newData: ITrafficDataPoint[]) => { + if (debounceTimeoutRef.current !== null) { + window.clearTimeout(debounceTimeoutRef.current); + } + debounceTimeoutRef.current = window.setTimeout(() => { + dispatchDisplayData(newData); + }, 50); // 50ms防抖 }, []); // 监听数据变化 useEffect(() => { const timeRangeData = getDataForTimeRange(timeRange); - updateDisplayDataDebounced(timeRangeData); - }, [ - dataPoints, - timeRange, - getDataForTimeRange, - updateDisplayDataDebounced, - ]); + updateDisplayData(timeRangeData); + + return () => { + if (debounceTimeoutRef.current !== null) { + window.clearTimeout(debounceTimeoutRef.current); + debounceTimeoutRef.current = null; + } + }; + }, [dataPoints, timeRange, getDataForTimeRange, updateDisplayData]); // Y轴坐标计算 - 基于刻度范围的线性映射 const calculateY = useCallback( diff --git a/src/components/home/enhanced-traffic-stats.tsx b/src/components/home/enhanced-traffic-stats.tsx index e731ac72..199bbd6f 100644 --- a/src/components/home/enhanced-traffic-stats.tsx +++ b/src/components/home/enhanced-traffic-stats.tsx @@ -278,7 +278,7 @@ export const EnhancedTrafficStats = () => { )} {/* 统计卡片区域 */} - {statCards.map((card, _index) => ( + {statCards.map((card) => ( diff --git a/src/components/home/system-info-card.tsx b/src/components/home/system-info-card.tsx index e9280efa..b2a397c4 100644 --- a/src/components/home/system-info-card.tsx +++ b/src/components/home/system-info-card.tsx @@ -16,7 +16,7 @@ import { } from "@mui/material"; import { check as checkUpdate } from "@tauri-apps/plugin-updater"; import { useLockFn } from "ahooks"; -import { useCallback, useEffect, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo, useReducer } from "react"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; import useSWR from "swr"; @@ -30,6 +30,29 @@ import { version as appVersion } from "@root/package.json"; import { EnhancedCard } from "./enhanced-card"; +interface SystemState { + osInfo: string; + lastCheckUpdate: string; +} + +type SystemStateAction = + | { type: "set-os-info"; payload: string } + | { type: "set-last-check-update"; payload: string }; + +const systemStateReducer = ( + state: SystemState, + action: SystemStateAction, +): SystemState => { + switch (action.type) { + case "set-os-info": + return { ...state, osInfo: action.payload }; + case "set-last-check-update": + return { ...state, lastCheckUpdate: action.payload }; + default: + return state; + } +}; + export const SystemInfoCard = () => { const { t } = useTranslation(); const { verge, patchVerge } = useVerge(); @@ -38,13 +61,15 @@ export const SystemInfoCard = () => { const { installServiceAndRestartCore } = useServiceInstaller(); // 系统信息状态 - const [systemState, setSystemState] = useState({ + const [systemState, dispatchSystemState] = useReducer(systemStateReducer, { osInfo: "", lastCheckUpdate: "-", }); // 初始化系统信息 useEffect(() => { + let timeoutId: number | undefined; + getSystemInfo() .then((info) => { const lines = info.split("\n"); @@ -59,10 +84,10 @@ export const SystemInfoCard = () => { sysVersion = sysVersion.substring(sysName.length).trim(); } - setSystemState((prev) => ({ - ...prev, - osInfo: `${sysName} ${sysVersion}`, - })); + dispatchSystemState({ + type: "set-os-info", + payload: `${sysName} ${sysVersion}`, + }); } }) .catch(console.error); @@ -73,10 +98,10 @@ export const SystemInfoCard = () => { try { const timestamp = parseInt(lastCheck, 10); if (!isNaN(timestamp)) { - setSystemState((prev) => ({ - ...prev, - lastCheckUpdate: new Date(timestamp).toLocaleString(), - })); + dispatchSystemState({ + type: "set-last-check-update", + payload: new Date(timestamp).toLocaleString(), + }); } } catch (e) { console.error("Error parsing last check update time", e); @@ -85,18 +110,23 @@ export const SystemInfoCard = () => { // 如果启用了自动检查更新但没有记录,设置当前时间并延迟检查 const now = Date.now(); localStorage.setItem("last_check_update", now.toString()); - setSystemState((prev) => ({ - ...prev, - lastCheckUpdate: new Date(now).toLocaleString(), - })); + dispatchSystemState({ + type: "set-last-check-update", + payload: new Date(now).toLocaleString(), + }); - setTimeout(() => { + timeoutId = window.setTimeout(() => { if (verge?.auto_check_update) { checkUpdate().catch(console.error); } }, 5000); } - }, [verge?.auto_check_update]); + return () => { + if (timeoutId !== undefined) { + window.clearTimeout(timeoutId); + } + }; + }, [verge?.auto_check_update, dispatchSystemState]); // 自动检查更新逻辑 useSWR( @@ -104,10 +134,10 @@ export const SystemInfoCard = () => { async () => { const now = Date.now(); localStorage.setItem("last_check_update", now.toString()); - setSystemState((prev) => ({ - ...prev, - lastCheckUpdate: new Date(now).toLocaleString(), - })); + dispatchSystemState({ + type: "set-last-check-update", + payload: new Date(now).toLocaleString(), + }); return await checkUpdate(); }, {