semi-xi / blog

blog
4 stars 1 forks source link

比较精妙的弹窗hook设计 #39

Open semi-xi opened 2 years ago

semi-xi commented 2 years ago
import { useRef, useState, useMemo, useCallback } from 'react'

export function usePromisifyConfirm<T = any>() {
  const [isOpen, toggle] = useState(false)
  const promiseRef = useRef<{ resolve: (value?: any) => void; reject: (reason?: any) => void }>()

  const open = useCallback(() => {
    toggle(true)

    return new Promise<T>((resolve, reject) => {
      promiseRef.current = { resolve, reject }
    })
  }, [toggle])

  const confirm = useCallback(
    (result?: T) => {
      toggle(false)

      if (typeof promiseRef?.current === 'object') {
        const { resolve } = promiseRef.current
        resolve(result)

        promiseRef.current = undefined
      }
    },
    [toggle]
  )

  const dismiss = useCallback(() => {
    toggle(false)

    if (typeof promiseRef?.current === 'object') {
      const { reject } = promiseRef.current
      reject('dismiss')

      promiseRef.current = undefined
    }
  }, [toggle])

  return useMemo(() => ({ isOpen, open, confirm, dismiss }), [isOpen, open, confirm, dismiss])
}