mirror of
https://github.com/woodchen-ink/clash-and-dashboard.git
synced 2025-07-18 14:01:56 +08:00
74 lines
2.4 KiB
TypeScript
74 lines
2.4 KiB
TypeScript
import { Draft } from 'immer'
|
|
import { useImmer } from 'use-immer'
|
|
import { createContainer } from 'unstated-next'
|
|
import { useRef, useEffect } from 'react'
|
|
|
|
import { noop } from '@lib/helper'
|
|
|
|
export function useObject<T extends object> (initialValue: T) {
|
|
const [copy, rawSet] = useImmer(initialValue)
|
|
|
|
function set<K extends keyof Draft<T>> (key: K, value: Draft<T>[K]): void
|
|
function set<K extends keyof Draft<T>> (data: Partial<T>): void
|
|
function set<K extends keyof Draft<T>> (f: (draft: Draft<T>) => void | T): void
|
|
function set<K extends keyof Draft<T>> (data: any, value?: Draft<T>[K]): void {
|
|
if (typeof data === 'string') {
|
|
rawSet(draft => {
|
|
const key = data as K
|
|
const v = value
|
|
draft[key] = v
|
|
})
|
|
} else if (typeof data === 'function') {
|
|
rawSet(data)
|
|
} else if (typeof data === 'object') {
|
|
rawSet((draft: Draft<T>) => {
|
|
const obj = data as Draft<T>
|
|
for (const key of Object.keys(obj)) {
|
|
const k = key as keyof Draft<T>
|
|
draft[k] = obj[k]
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
return [copy, set] as [T, typeof set]
|
|
}
|
|
|
|
export function useInterval (callback: () => void, delay: number) {
|
|
const savedCallback = useRef(noop)
|
|
|
|
useEffect(() => savedCallback.current = callback, [callback])
|
|
|
|
useEffect(
|
|
() => {
|
|
const handler = () => savedCallback.current()
|
|
|
|
if (delay !== null) {
|
|
const id = setInterval(handler, delay)
|
|
return () => clearInterval(id)
|
|
}
|
|
},
|
|
[delay]
|
|
)
|
|
}
|
|
|
|
type containerFn<Value, State = void> = (initialState?: State) => Value
|
|
|
|
export function composeContainer<T, C extends containerFn<T>, U extends { [key: string]: C }, K extends keyof U> (mapping: U) {
|
|
function Global () {
|
|
return Object.keys(mapping).reduce((obj, key) => {
|
|
obj[key as K] = 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 as K] = (() => allContainer.useContainer()[key]) as U[K]
|
|
return obj
|
|
}, {} as { [K in keyof U]: U[K] })
|
|
}
|
|
}
|