Chore: compose unstate store

This commit is contained in:
Dreamacro 2019-07-04 14:04:16 +08:00
parent 760f0fda72
commit 0fe722d28d
8 changed files with 48 additions and 35 deletions

View File

@ -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: '',

View File

@ -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) {

View File

@ -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(() => {

View File

@ -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

View File

@ -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,

View File

@ -1,5 +1,6 @@
import { Draft } from 'immer'
import { useImmer } from 'use-immer'
import { createContainer } from 'unstated-next'
export function useObject<T extends object> (initialValue: T) {
let [copy, setCopy] = useImmer(initialValue)
@ -20,3 +21,25 @@ export function useObject<T extends object> (initialValue: T) {
}
return { value: copy, change, set }
}
type containerFn<Value, State = void> = (initialState?: State) => Value
export function composeContainer<T, C = containerFn<T>, 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] }
}
}

View File

@ -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 (
<APIInfo.Provider>
<Data.Provider>
<ClashXData.Provider>
{ props.children }
</ClashXData.Provider>
</Data.Provider>
</APIInfo.Provider>
)
}
export default function renderApp () {
const rootEl = document.getElementById('root')
const AppInstance = (
<Store>
<Global>
<HashRouter>
<I18nextProvider i18n={ i18n }>
<App />
</I18nextProvider>
</HashRouter>
</Store>
</Global>
)
render(AppInstance, rootEl)

View File

@ -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 }