From 0fe722d28d65dd90db559a0acca12b1cf3a68b8e Mon Sep 17 00:00:00 2001 From: Dreamacro <305009791@qq.com> Date: Thu, 4 Jul 2019 14:04:16 +0800 Subject: [PATCH] Chore: compose unstate store --- .../ExternalControllerDrawer/index.tsx | 6 ++--- .../Proxies/components/Group/index.tsx | 4 ++-- src/containers/Proxies/index.tsx | 4 ++-- src/containers/Rules/index.tsx | 6 ++--- src/containers/Settings/index.tsx | 8 +++---- src/lib/hook.ts | 23 +++++++++++++++++++ src/render.tsx | 19 +++------------ src/stores/HookStore.ts | 13 +++++++---- 8 files changed, 48 insertions(+), 35 deletions(-) diff --git a/src/containers/ExternalControllerDrawer/index.tsx b/src/containers/ExternalControllerDrawer/index.tsx index f04055a..975e12e 100644 --- a/src/containers/ExternalControllerDrawer/index.tsx +++ b/src/containers/ExternalControllerDrawer/index.tsx @@ -2,13 +2,13 @@ import React, { useEffect } from 'react' import { useTranslation } from 'react-i18next' import { useObject } from '@lib/hook' import { Modal, Input, Row, Col, Alert } from '@components' -import { APIInfo, Data } from '@stores' +import { containers } from '@stores' import './style.scss' export default function ExternalController () { const { t } = useTranslation(['Settings']) - const { data: info, update, fetch } = APIInfo.useContainer() - const { unauthorized: { hidden, visible } } = Data.useContainer() + const { data: info, update, fetch } = containers.useAPIInfo() + const { unauthorized: { hidden, visible } } = containers.useData() const { value, set, change } = useObject({ hostname: '', port: '', diff --git a/src/containers/Proxies/components/Group/index.tsx b/src/containers/Proxies/components/Group/index.tsx index cb4f7db..f2e01c0 100644 --- a/src/containers/Proxies/components/Group/index.tsx +++ b/src/containers/Proxies/components/Group/index.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import { Data } from '@stores' +import { containers } from '@stores' import { changeProxySelected, Group as IGroup } from '@lib/request' import { Tags } from '@components' import './style.scss' @@ -9,7 +9,7 @@ interface GroupProps { } export function Group (props: GroupProps) { - const { fetch } = Data.useContainer() + const { fetch } = containers.useData() const { config } = props async function handleChangeProxySelected (name: string) { diff --git a/src/containers/Proxies/index.tsx b/src/containers/Proxies/index.tsx index 7fd0334..5031a01 100644 --- a/src/containers/Proxies/index.tsx +++ b/src/containers/Proxies/index.tsx @@ -2,13 +2,13 @@ import React, { useLayoutEffect } from 'react' import { useTranslation } from 'react-i18next' import EE from '@lib/event' import { Card, Header, Icon } from '@components' -import { Data } from '@stores' +import { containers } from '@stores' import { Proxy, Group } from './components' import './style.scss' export default function Proxies () { - const { data, fetch } = Data.useContainer() + const { data, fetch } = containers.useData() const { t } = useTranslation(['Proxies']) useLayoutEffect(() => { diff --git a/src/containers/Rules/index.tsx b/src/containers/Rules/index.tsx index bfa632d..bbeb1b1 100644 --- a/src/containers/Rules/index.tsx +++ b/src/containers/Rules/index.tsx @@ -1,12 +1,12 @@ import React, { useEffect } from 'react' import { useTranslation } from 'react-i18next' import { Header, Card, Row, Col } from '@components' -import './style.scss' -import { Data } from '@stores' +import { containers } from '@stores' import { List, AutoSizer } from 'react-virtualized' +import './style.scss' export default function Rules () { - const { data, fetch } = Data.useContainer() + const { data, fetch } = containers.useData() const { t } = useTranslation(['Rules']) const { rules } = data diff --git a/src/containers/Settings/index.tsx b/src/containers/Settings/index.tsx index 393fceb..55b32c4 100644 --- a/src/containers/Settings/index.tsx +++ b/src/containers/Settings/index.tsx @@ -2,7 +2,7 @@ import React, { useEffect } from 'react' import { useTranslation } from 'react-i18next' import i18next from 'i18next' import { Header, Card, Row, Col, Switch, ButtonSelect, ButtonSelectOptions, Input, Icon } from '@components' -import { APIInfo, Data, ClashXData } from '@stores' +import { containers } from '@stores' import { updateConfig } from '@lib/request' import { useObject } from '@lib/hook' import { to } from '@lib/helper' @@ -24,9 +24,9 @@ async function handleSetSystemProxy (state: boolean) { } export default function Settings () { - const { data: clashXData, fetch: fetchClashXData } = ClashXData.useContainer() - const { data, fetch, unauthorized: { show } } = Data.useContainer() - const { data: apiInfo } = APIInfo.useContainer() + const { data: clashXData, fetch: fetchClashXData } = containers.useClashXData() + const { data, fetch, unauthorized: { show } } = containers.useData() + const { data: apiInfo } = containers.useAPIInfo() const { t, i18n } = useTranslation(['Settings']) const { value: info, change } = useObject({ socks5ProxyPort: 7891, diff --git a/src/lib/hook.ts b/src/lib/hook.ts index ad51f8d..654f988 100644 --- a/src/lib/hook.ts +++ b/src/lib/hook.ts @@ -1,5 +1,6 @@ import { Draft } from 'immer' import { useImmer } from 'use-immer' +import { createContainer } from 'unstated-next' export function useObject (initialValue: T) { let [copy, setCopy] = useImmer(initialValue) @@ -20,3 +21,25 @@ export function useObject (initialValue: T) { } return { value: copy, change, set } } + +type containerFn = (initialState?: State) => Value + +export function composeContainer, U = { [key: string]: C }> (mapping: U) { + function Global () { + return Object.keys(mapping).reduce((obj, key) => { + obj[key] = mapping[key]() + return obj + }, {}) as { [K in keyof U]: T } + } + + const allContainer = createContainer(Global) + return { + Provider: allContainer.Provider, + containers: Object.keys(mapping).reduce((obj, key) => { + obj[key] = function () { + return allContainer.useContainer()[key] + } + return obj + }, {}) as { [K in keyof U]: U[K] } + } +} diff --git a/src/render.tsx b/src/render.tsx index f7765c1..543ce22 100644 --- a/src/render.tsx +++ b/src/render.tsx @@ -2,33 +2,20 @@ import * as React from 'react' import { render } from 'react-dom' import { HashRouter } from 'react-router-dom' import { I18nextProvider } from 'react-i18next' -import { BaseComponentProps } from '@models/BaseProps' -import { APIInfo, Data, ClashXData } from '@stores' +import { Provider as Global } from '@stores' import App from '@containers/App' import i18n from '@i18n' -function Store (props: BaseComponentProps) { - return ( - - - - { props.children } - - - - ) -} - export default function renderApp () { const rootEl = document.getElementById('root') const AppInstance = ( - + - + ) render(AppInstance, rootEl) diff --git a/src/stores/HookStore.ts b/src/stores/HookStore.ts index 6f4fce2..3f8dfac 100644 --- a/src/stores/HookStore.ts +++ b/src/stores/HookStore.ts @@ -1,8 +1,7 @@ import { useState } from 'react' import * as Models from '@models' -import { createContainer } from 'unstated-next' import * as API from '@lib/request' -import { useObject } from '@lib/hook' +import { useObject, composeContainer } from '@lib/hook' import { jsBridge } from '@lib/jsBridge' import { setLocalStorageItem, partition, to } from '@lib/helper' @@ -96,6 +95,10 @@ function useClashXData () { return { data, fetch } } -export const Data = createContainer(useData) -export const APIInfo = createContainer(useAPIInfo) -export const ClashXData = createContainer(useClashXData) +const { Provider, containers } = composeContainer({ + useData, + useAPIInfo, + useClashXData +}) + +export { Provider, containers }