Chore: improve swr use

This commit is contained in:
Dreamacro 2020-08-16 00:34:15 +08:00
parent 6265c5adb1
commit 1c45cc16e6
5 changed files with 53 additions and 98 deletions

View File

@ -1,5 +1,4 @@
import React, { useMemo } from 'react' import React, { useMemo } from 'react'
import useSWR from 'swr'
import EE from '@lib/event' import EE from '@lib/event'
import { useRound } from '@lib/hook' import { useRound } from '@lib/hook'
import { Card, Header, Icon, Checkbox } from '@components' import { Card, Header, Icon, Checkbox } from '@components'
@ -68,12 +67,10 @@ function ProxyGroups () {
} }
function ProxyProviders () { function ProxyProviders () {
const { providers, update } = useProxyProviders() const { providers } = useProxyProviders()
const { useTranslation } = useI18n() const { useTranslation } = useI18n()
const { t } = useTranslation('Proxies') const { t } = useTranslation('Proxies')
useSWR('providers', update)
return <> return <>
{ {
providers.length !== 0 && providers.length !== 0 &&
@ -95,12 +92,9 @@ function ProxyProviders () {
function Proxies () { function Proxies () {
const { proxies } = useProxy() const { proxies } = useProxy()
const { update: updateGeneral } = useGeneral()
const { useTranslation } = useI18n() const { useTranslation } = useI18n()
const { t } = useTranslation('Proxies') const { t } = useTranslation('Proxies')
useSWR('general', updateGeneral)
function handleNotitySpeedTest () { function handleNotitySpeedTest () {
EE.notifySpeedTest() EE.notifySpeedTest()
} }
@ -144,9 +138,6 @@ function Proxies () {
} }
export default function ProxyContainer () { export default function ProxyContainer () {
const { update: updateProxy } = useProxy()
useSWR('proxies', updateProxy)
return ( return (
<div className="page"> <div className="page">
<ProxyGroups /> <ProxyGroups />

View File

@ -1,6 +1,6 @@
import React, { useLayoutEffect } from 'react' import React from 'react'
import { Header, Card, Row, Col } from '@components' import { Header, Card, Row, Col } from '@components'
import { useI18n, useRule, useRuleProviders, useVersion } from '@stores' import { useI18n, useRule, useRuleProviders } from '@stores'
import { FixedSizeList as List } from 'react-window' import { FixedSizeList as List } from 'react-window'
import AutoSizer from 'react-virtualized-auto-sizer' import AutoSizer from 'react-virtualized-auto-sizer'
import useSWR from 'swr' import useSWR from 'swr'
@ -8,17 +8,10 @@ import { Provider } from './Provider'
import './style.scss' import './style.scss'
function RuleProviders () { function RuleProviders () {
const { providers, update } = useRuleProviders() const { providers } = useRuleProviders()
const { premium } = useVersion()
const { useTranslation } = useI18n() const { useTranslation } = useI18n()
const { t } = useTranslation('Rules') const { t } = useTranslation('Rules')
useLayoutEffect(() => {
if (premium) {
update()
}
}, [premium])
return <> return <>
{ {
providers.length !== 0 && providers.length !== 0 &&

View File

@ -25,11 +25,6 @@ export default function Settings () {
mixedProxyPort: 0 mixedProxyPort: 0
}) })
useEffect(() => {
fetchGeneral()
fetchClashXData()
}, [])
useEffect(() => { useEffect(() => {
set('socks5ProxyPort', general?.socksPort ?? 0) set('socks5ProxyPort', general?.socksPort ?? 0)
set('httpProxyPort', general?.port ?? 0) set('httpProxyPort', general?.port ?? 0)
@ -81,10 +76,10 @@ export default function Settings () {
} = apiInfo } = apiInfo
const { allowLan, mode } = general const { allowLan, mode } = general
const {
startAtLogin, const startAtLogin = clashXData?.startAtLogin ?? false
systemProxy const systemProxy = clashXData?.systemProxy ?? false
} = clashXData const isClashX = clashXData?.isClashX ?? false
const proxyModeOptions = useMemo(() => { const proxyModeOptions = useMemo(() => {
const options = [ const options = [
@ -108,7 +103,7 @@ export default function Settings () {
<span className="label">{t('labels.startAtLogin')}</span> <span className="label">{t('labels.startAtLogin')}</span>
</Col> </Col>
<Col span={8} className="value-column"> <Col span={8} className="value-column">
<Switch disabled={!clashXData.isClashX} checked={startAtLogin} onChange={handleStartAtLoginChange} /> <Switch disabled={!clashXData?.isClashX} checked={startAtLogin} onChange={handleStartAtLoginChange} />
</Col> </Col>
</Col> </Col>
<Col span={12}> <Col span={12}>
@ -127,7 +122,7 @@ export default function Settings () {
</Col> </Col>
<Col span={8} className="value-column"> <Col span={8} className="value-column">
<Switch <Switch
disabled={!clashXData.isClashX} disabled={!isClashX}
checked={systemProxy} checked={systemProxy}
onChange={handleSetSystemProxy} onChange={handleSetSystemProxy}
/> />
@ -167,7 +162,7 @@ export default function Settings () {
</Col> </Col>
<Col span={8}> <Col span={8}>
<Input <Input
disabled={clashXData.isClashX} disabled={isClashX}
value={info.socks5ProxyPort} value={info.socks5ProxyPort}
onChange={socks5ProxyPort => set('socks5ProxyPort', +socks5ProxyPort)} onChange={socks5ProxyPort => set('socks5ProxyPort', +socks5ProxyPort)}
onBlur={handleSocksPortSave} onBlur={handleSocksPortSave}
@ -182,7 +177,7 @@ export default function Settings () {
</Col> </Col>
<Col span={8}> <Col span={8}>
<Input <Input
disabled={clashXData.isClashX} disabled={isClashX}
value={info.httpProxyPort} value={info.httpProxyPort}
onChange={httpProxyPort => set('httpProxyPort', +httpProxyPort)} onChange={httpProxyPort => set('httpProxyPort', +httpProxyPort)}
onBlur={handleHttpPortSave} onBlur={handleHttpPortSave}
@ -195,7 +190,7 @@ export default function Settings () {
</Col> </Col>
<Col span={8}> <Col span={8}>
<Input <Input
disabled={clashXData.isClashX} disabled={isClashX}
value={info.mixedProxyPort} value={info.mixedProxyPort}
onChange={mixedProxyPort => set('mixedProxyPort', +mixedProxyPort)} onChange={mixedProxyPort => set('mixedProxyPort', +mixedProxyPort)}
onBlur={handleMixedPortSave} onBlur={handleMixedPortSave}
@ -210,8 +205,8 @@ export default function Settings () {
</Col> </Col>
<Col className="external-controller" span={10}> <Col className="external-controller" span={10}>
<span <span
className={classnames({ 'modify-btn': !clashXData.isClashX })} className={classnames({ 'modify-btn': !isClashX })}
onClick={() => !clashXData.isClashX && setIdentity(false)}> onClick={() => !isClashX && setIdentity(false)}>
{`${externalControllerHost}:${externalControllerPort}`} {`${externalControllerHost}:${externalControllerPort}`}
</span> </span>
</Col> </Col>

View File

@ -20,11 +20,10 @@ export default function Sidebar (props: SidebarProps) {
const { routes } = props const { routes } = props
const { useTranslation } = useI18n() const { useTranslation } = useI18n()
const { version, premium, update } = useVersion() const { version, premium, update } = useVersion()
const { data: { isClashX }, update: updateClashXData } = useClashXData() const { data } = useClashXData()
const { t } = useTranslation('SideBar') const { t } = useTranslation('SideBar')
useSWR('version', update) useSWR('version', update)
useSWR('clashx', updateClashXData)
const navlinks = routes.map( const navlinks = routes.map(
({ path, name, exact, noMobile }) => ( ({ path, name, exact, noMobile }) => (
@ -41,7 +40,7 @@ export default function Sidebar (props: SidebarProps) {
{ navlinks } { navlinks }
</ul> </ul>
<div className="sidebar-version"> <div className="sidebar-version">
<span className="sidebar-version-label">Clash{ isClashX && 'X' } { t('Version') }</span> <span className="sidebar-version-label">Clash{ data?.isClashX && 'X' } { t('Version') }</span>
<span className="sidebar-version-text">{ version }</span> <span className="sidebar-version-text">{ version }</span>
{ premium && <span className="sidebar-version-label">Premium</span> } { premium && <span className="sidebar-version-label">Premium</span> }
</div> </div>

View File

@ -1,8 +1,8 @@
import { atom, useRecoilState, selector } from 'recoil' import { atom, useRecoilState, selector } from 'recoil'
import get from 'lodash/get' import get from 'lodash/get'
import throttle from 'lodash/throttle' import { useCallback, useEffect } from 'react'
import { useCallback } from 'react'
import { AxiosError } from 'axios' import { AxiosError } from 'axios'
import swr from 'swr'
import { getLanguage, setLanguage, Lang, locales, Language } from '@i18n' import { getLanguage, setLanguage, Lang, locales, Language } from '@i18n'
import { useRecoilObjectWithImmer } from '@lib/recoil' import { useRecoilObjectWithImmer } from '@lib/recoil'
@ -108,59 +108,43 @@ export const proxyProvider = atom({
}) })
export function useProxyProviders () { export function useProxyProviders () {
const [data, set] = useRecoilState(proxyProvider) const [providers, set] = useRecoilState(proxyProvider)
async function update () { const { data, mutate } = swr('/providers/proxy', async () => {
const proxyProviders = await API.getProxyProviders() const proxyProviders = await API.getProxyProviders()
const providers = Object.keys(proxyProviders.data.providers) return Object.keys(proxyProviders.data.providers)
.map<API.Provider>(name => proxyProviders.data.providers[name]) .map<API.Provider>(name => proxyProviders.data.providers[name])
.filter(pd => pd.name !== 'default') .filter(pd => pd.name !== 'default')
.filter(pd => pd.vehicleType !== 'Compatible') .filter(pd => pd.vehicleType !== 'Compatible')
})
set(providers) useEffect(() => set(data ?? []), [data, set])
} return { providers, update: mutate }
return { providers: data, update }
} }
export const ruleProvider = atom({
key: 'ruleProvider',
default: [] as API.RuleProvider[]
})
export function useRuleProviders () { export function useRuleProviders () {
const [data, set] = useRecoilState(ruleProvider)
const [{ premium }] = useRecoilState(version) const [{ premium }] = useRecoilState(version)
async function update () { const { data, mutate } = swr('/providers/rule', async () => {
if (!premium) { if (!premium) {
return return []
} }
const ruleProviders = await API.getRuleProviders() const ruleProviders = await API.getRuleProviders()
const providers = Object.keys(ruleProviders.data.providers) return Object.keys(ruleProviders.data.providers)
.map<API.RuleProvider>(name => ruleProviders.data.providers[name]) .map<API.RuleProvider>(name => ruleProviders.data.providers[name])
})
set(providers) return { providers: data ?? [], update: mutate }
}
return { providers: data, update }
} }
export const general = atom({
key: 'general',
default: {} as Models.Data['general']
})
export function useGeneral () { export function useGeneral () {
const [data, set] = useRecoilState(general) const { data, mutate } = swr('/config', async () => {
async function update () {
const resp = await API.getConfig() const resp = await API.getConfig()
const data = resp.data const data = resp.data
set({ return {
port: data.port, port: data.port,
socksPort: data['socks-port'], socksPort: data['socks-port'],
mixedPort: data['mixed-port'] ?? 0, mixedPort: data['mixed-port'] ?? 0,
@ -168,10 +152,10 @@ export function useGeneral () {
mode: data.mode.toLowerCase() as Models.Data['general']['mode'], mode: data.mode.toLowerCase() as Models.Data['general']['mode'],
logLevel: data['log-level'], logLevel: data['log-level'],
allowLan: data['allow-lan'] allowLan: data['allow-lan']
} as Models.Data['general']
}) })
}
return { general: data, update: throttle(update, 50) } return { general: data ?? {} as Models.Data['general'], update: mutate }
} }
export const proxies = atom({ export const proxies = atom({
@ -184,9 +168,9 @@ export const proxies = atom({
}) })
export function useProxy () { export function useProxy () {
const [data, set] = useRecoilObjectWithImmer(proxies) const [allProxy, set] = useRecoilObjectWithImmer(proxies)
async function update () { const { data, mutate } = swr('/proxies', async () => {
const allProxies = await API.getProxies() const allProxies = await API.getProxies()
const global = allProxies.data.proxies.GLOBAL as API.Group const global = allProxies.data.proxies.GLOBAL as API.Group
@ -199,15 +183,15 @@ export function useProxy () {
.filter(key => !unUsedProxy.has(key)) .filter(key => !unUsedProxy.has(key))
.map(key => ({ ...allProxies.data.proxies[key], name: key })) .map(key => ({ ...allProxies.data.proxies[key], name: key }))
const [proxy, groups] = partition(proxies, proxy => !policyGroup.has(proxy.type)) const [proxy, groups] = partition(proxies, proxy => !policyGroup.has(proxy.type))
return { proxies: proxy as API.Proxy[], groups: groups as API.Group[], global: global }
set({ proxies: proxy as API.Proxy[], groups: groups as API.Group[], global: global }) })
} useEffect(() => data && set(data), [data, set])
return { return {
proxies: data.proxies, proxies: allProxy.proxies,
groups: data.groups, groups: allProxy.groups,
global: data.global, global: allProxy.global,
update, update: mutate,
set set
} }
} }
@ -232,30 +216,23 @@ export const proxyMapping = selector({
} }
}) })
export const clashxData = atom({ export function useClashXData () {
key: 'clashxData', const { data, mutate } = swr('/clashx', async () => {
default: { if (!isClashX()) {
return {
isClashX: false, isClashX: false,
startAtLogin: false, startAtLogin: false,
systemProxy: false systemProxy: false
} }
})
export function useClashXData () {
const [data, set] = useRecoilState(clashxData)
async function update () {
if (!isClashX()) {
return
} }
const startAtLogin = await jsBridge?.getStartAtLogin() ?? false const startAtLogin = await jsBridge?.getStartAtLogin() ?? false
const systemProxy = await jsBridge?.isSystemProxySet() ?? false const systemProxy = await jsBridge?.isSystemProxySet() ?? false
set({ startAtLogin, systemProxy, isClashX: true }) return { startAtLogin, systemProxy, isClashX: true }
} })
return { data, update } return { data, update: mutate }
} }
export const apiData = atom({ export const apiData = atom({