import { isFunction } from './common/is-function' import { DependencyList, Dispatch, MutableRefObject, SetStateAction, useDebugValue, useRef } from 'react' import { useRender } from "./render" import { useRun } from "./run" import { useInitial } from "./initial" import { NonFunction } from './common/non-function.type' type useSuperState = { (): readonly [S | undefined, Dispatch>, MutableRefObject] (initialState: () => S): readonly [S, Dispatch>, MutableRefObject] (initialState: NonFunction): readonly [S, Dispatch>, MutableRefObject] (factory: () => S, deps: DependencyList): readonly [S, Dispatch>, MutableRefObject] (factory: (prev: S) => S, deps: DependencyList): readonly [S, Dispatch>, MutableRefObject] } export const useSuperState: useSuperState = (factory?: S | ((prev: S) => S), deps: DependencyList = []) => { const render = useRender() const ref = useRef() const setState = useInitial(() => (value?: SetStateAction) => { const prev = ref.current ref.current = isFunction(value) ? value(prev) : value if (ref.current !== prev) render() }) useRun(() => ref.current = isFunction(factory) ? factory(ref.current) : factory, deps) useDebugValue(ref.current) return [ref.current, setState, ref] }