perf: narrow app data subscriptions

This commit is contained in:
Tunglies
2026-04-29 10:18:03 +08:00
parent 33d7988ac9
commit 6e0647f7b2
17 changed files with 136 additions and 45 deletions
+10 -2
View File
@@ -4,7 +4,12 @@ import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { useClash } from '@/hooks/use-clash'
import { useAppData } from '@/providers/app-data-context'
import {
useClashConfigData,
useRulesData,
useSystemData,
useUptimeData,
} from '@/providers/app-data-context'
import { EnhancedCard } from './enhanced-card'
@@ -19,7 +24,10 @@ const formatUptime = (uptimeMs: number) => {
export const ClashInfoCard = () => {
const { t } = useTranslation()
const { version: clashVersion } = useClash()
const { clashConfig, rules, uptime, systemProxyAddress } = useAppData()
const { clashConfig } = useClashConfigData()
const { rules } = useRulesData()
const { uptime } = useUptimeData()
const { systemProxyAddress } = useSystemData()
// 使用useMemo缓存格式化后的uptime,避免频繁计算
const formattedUptime = useMemo(() => formatUptime(uptime), [uptime])
+8 -2
View File
@@ -10,7 +10,11 @@ import { useTranslation } from 'react-i18next'
import { closeAllConnections } from 'tauri-plugin-mihomo-api'
import { useVerge } from '@/hooks/use-verge'
import { useAppData } from '@/providers/app-data-context'
import {
useAppRefreshers,
useClashConfigData,
useCoreDataStatus,
} from '@/providers/app-data-context'
import { patchClashMode } from '@/services/cmds'
import type { TranslationKey } from '@/types/generated/i18n-keys'
@@ -41,7 +45,9 @@ const MODE_META: Record<
export const ClashModeCard = () => {
const { t } = useTranslation()
const { verge } = useVerge()
const { clashConfig, isCoreDataPending, refreshClashConfig } = useAppData()
const { clashConfig } = useClashConfigData()
const { isCoreDataPending } = useCoreDataStatus()
const { refreshClashConfig } = useAppRefreshers()
// 支持的模式列表
const modeList = CLASH_MODES
+12 -3
View File
@@ -37,7 +37,13 @@ import { EnhancedCard } from '@/components/home/enhanced-card'
import { useProfiles } from '@/hooks/use-profiles'
import { useProxySelection } from '@/hooks/use-proxy-selection'
import { useVerge } from '@/hooks/use-verge'
import { useAppData } from '@/providers/app-data-context'
import {
useAppRefreshers,
useClashConfigData,
useCoreDataStatus,
useProxiesData,
useRulesData,
} from '@/providers/app-data-context'
import delayManager from '@/services/delay'
import { debugLog } from '@/utils/debug'
@@ -105,8 +111,11 @@ export const CurrentProxyCard = () => {
const { t } = useTranslation()
const navigate = useNavigate()
const theme = useTheme()
const { proxies, clashConfig, isCoreDataPending, refreshProxy, rules } =
useAppData()
const { proxies } = useProxiesData()
const { clashConfig } = useClashConfigData()
const { rules } = useRulesData()
const { refreshProxy } = useAppRefreshers()
const { isCoreDataPending } = useCoreDataStatus()
const { verge } = useVerge()
const { current: currentProfile } = useProfiles()
const autoDelayEnabled = verge?.enable_auto_delay_detection ?? false
+2 -2
View File
@@ -24,7 +24,7 @@ import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router'
import { useAppData } from '@/providers/app-data-context'
import { useAppRefreshers } from '@/providers/app-data-context'
import { openWebUrl, updateProfile } from '@/services/cmds'
import { showNotice } from '@/services/notice-service'
import parseTraffic from '@/utils/parse-traffic'
@@ -281,7 +281,7 @@ export const HomeProfileCard = ({
}: HomeProfileCardProps) => {
const { t } = useTranslation()
const navigate = useNavigate()
const { refreshAll } = useAppData()
const { refreshAll } = useAppRefreshers()
// 更新当前订阅
const [updating, setUpdating] = useState(false)
+3 -2
View File
@@ -22,7 +22,7 @@ import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { updateProxyProvider } from 'tauri-plugin-mihomo-api'
import { useAppData } from '@/providers/app-data-context'
import { useAppRefreshers, useProxiesData } from '@/providers/app-data-context'
import { showNotice } from '@/services/notice-service'
import parseTraffic from '@/utils/parse-traffic'
@@ -48,7 +48,8 @@ const parseExpire = (expire?: number) => {
export const ProviderButton = () => {
const { t } = useTranslation()
const [open, setOpen] = useState(false)
const { proxyProviders, refreshProxy, refreshProxyProviders } = useAppData()
const { proxyProviders } = useProxiesData()
const { refreshProxy, refreshProxyProviders } = useAppRefreshers()
const [updating, setUpdating] = useState<Record<string, boolean>>({})
// 检查是否有提供者
+3 -2
View File
@@ -40,7 +40,7 @@ import {
selectNodeForGroup,
} from 'tauri-plugin-mihomo-api'
import { useAppData } from '@/providers/app-data-context'
import { useAppRefreshers, useProxiesData } from '@/providers/app-data-context'
import { updateProxyChainConfigInRuntime } from '@/services/cmds'
import { debugLog } from '@/utils/debug'
@@ -251,7 +251,8 @@ export const ProxyChain = ({
}: ProxyChainProps) => {
const theme = useTheme()
const { t } = useTranslation()
const { proxies, refreshProxy } = useAppData()
const { proxies } = useProxiesData()
const { refreshProxy } = useAppRefreshers()
const [isConnecting, setIsConnecting] = useState(false)
const markUnsavedChanges = useCallback(() => {
onMarkUnsavedChanges?.()
+3 -3
View File
@@ -19,7 +19,7 @@ import { delayGroup, healthcheckProxyProvider } from 'tauri-plugin-mihomo-api'
import { BaseEmpty } from '@/components/base'
import { useProxySelection } from '@/hooks/use-proxy-selection'
import { useVerge } from '@/hooks/use-verge'
import { useAppData } from '@/providers/app-data-context'
import { useProxiesData } from '@/providers/app-data-context'
import { calcuProxies, updateProxyChainConfigInRuntime } from '@/services/cmds'
import delayManager from '@/services/delay'
import { debugLog } from '@/utils/debug'
@@ -57,7 +57,7 @@ export const ProxyGroups = (props: Props) => {
const { t } = useTranslation()
const { mode, isChainMode = false, chainConfigData } = props
// Drive 3s polling on the shared TQ cache; data is read via useAppData() below
// Drive 3s polling on the shared TQ cache; data is read via granular context below
useQuery({
queryKey: ['getProxies'],
queryFn: calcuProxies,
@@ -95,7 +95,7 @@ export const ProxyGroups = (props: Props) => {
}>({ open: false, message: '' })
const { verge } = useVerge()
const { proxies: proxiesData } = useAppData()
const { proxies: proxiesData } = useProxiesData()
const groups = proxiesData?.groups
const availableGroups = useMemo(() => {
if (!groups) return []
+3 -2
View File
@@ -2,7 +2,7 @@ import { useEffect, useMemo, useRef } from 'react'
import { useRuntimeConfig } from '@/hooks/use-clash'
import { useVerge } from '@/hooks/use-verge'
import { useAppData } from '@/providers/app-data-context'
import { useAppRefreshers, useProxiesData } from '@/providers/app-data-context'
import delayManager from '@/services/delay'
import { debugLog } from '@/utils/debug'
@@ -108,7 +108,8 @@ export const useRenderList = (
selectedGroup?: string | null,
) => {
// 使用全局数据提供者
const { proxies: proxiesData, refreshProxy } = useAppData()
const { proxies: proxiesData } = useProxiesData()
const { refreshProxy } = useAppRefreshers()
const { verge } = useVerge()
const { width } = useWindowWidth()
const [headStates, setHeadState] = useHeadStateNew()
+3 -2
View File
@@ -21,7 +21,7 @@ import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { updateRuleProvider } from 'tauri-plugin-mihomo-api'
import { useAppData } from '@/providers/app-data-context'
import { useAppRefreshers, useRulesData } from '@/providers/app-data-context'
import { showNotice } from '@/services/notice-service'
// 辅助组件 - 类型框
@@ -40,7 +40,8 @@ const TypeBox = styled(Box)<{ component?: React.ElementType }>(({ theme }) => ({
export const ProviderButton = () => {
const { t } = useTranslation()
const [open, setOpen] = useState(false)
const { ruleProviders, refreshRules, refreshRuleProviders } = useAppData()
const { ruleProviders } = useRulesData()
const { refreshRules, refreshRuleProviders } = useAppRefreshers()
const [updating, setUpdating] = useState<Record<string, boolean>>({})
// 检查是否有提供者
@@ -34,7 +34,7 @@ import {
import { EditorViewer } from '@/components/profile/editor-viewer'
import { useSystemProxyState } from '@/hooks/use-system-proxy-state'
import { useVerge } from '@/hooks/use-verge'
import { useAppData } from '@/providers/app-data-context'
import { useClashConfigData, useSystemData } from '@/providers/app-data-context'
import {
getAutotemProxy,
getNetworkInterfacesInfo,
@@ -108,7 +108,7 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
const { verge, patchVerge, mutateVerge } = useVerge()
const [hostOptions, setHostOptions] = useState<string[]>([])
const { clashConfig } = useAppData()
const { clashConfig } = useClashConfigData()
const { indicator: isProxyReallyEnabled, invalidateProxyState } =
useSystemProxyState()
@@ -179,7 +179,7 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
updateProxy()
}, [clashConfig?.mixedPort, enabled, value.pac, invalidateProxyState])
const { systemProxyAddress } = useAppData()
const { systemProxyAddress } = useSystemData()
// 为当前状态计算系统代理地址
const getSystemProxyAddress = useMemo(() => {
@@ -16,7 +16,7 @@ import { useTranslation } from 'react-i18next'
import { BaseDialog } from '@/components/base'
import { useClash } from '@/hooks/use-clash'
import { useAppData } from '@/providers/app-data-context'
import { useProxiesData } from '@/providers/app-data-context'
import { isPortInUse } from '@/services/cmds'
import { showNotice } from '@/services/notice-service'
import {
@@ -92,7 +92,7 @@ export const TunnelsViewer = forwardRef<TunnelsViewerRef>((_, ref) => {
})
}, [draftTunnels])
const { proxies } = useAppData()
const { proxies } = useProxiesData()
const proxyGroups = useMemo<IProxyGroupItem[]>(() => {
return proxies?.groups ?? []