/* eslint-disable no-redeclare */ import { useRecoilState, RecoilState } from 'recoil' import produce, { Draft } from 'immer' import { useMemo } from 'react' export function useRecoilObjectWithImmer (value: RecoilState) { const [copy, rawSet] = useRecoilState(value) const set = useMemo(() => { function set> (key: K, value: Draft[K]): void function set (data: Partial): void function set (f: (draft: Draft) => void | T): void function set> (data: any, value?: Draft[K]): void { if (typeof data === 'string') { rawSet(pre => produce(pre, (draft: Draft) => { const key = data as K const v = value draft[key] = v! })) } else if (typeof data === 'function') { const fn = data as (draft: Draft) => void | T rawSet(pre => produce(pre, fn) as T) } else if (typeof data === 'object') { rawSet(pre => produce(pre, (draft: Draft) => { const obj = data as Draft for (const key of Object.keys(obj)) { const k = key as keyof Draft draft[k] = obj[k] } })) } } return set }, [rawSet]) return [copy, set] as [T, typeof set] }