2023-05-25 05:59:55 -04:00
|
|
|
import { useRef, useEffect, useCallback, useState } from 'react'
|
2020-11-26 09:22:30 -05:00
|
|
|
|
2022-09-26 05:35:54 -04:00
|
|
|
export function useRefWithAutoFocus<T extends HTMLElement = HTMLElement>() {
|
2022-09-15 05:58:35 -04:00
|
|
|
const autoFocusedRef = useRef<T>(null)
|
2023-05-25 05:59:55 -04:00
|
|
|
const [hasFocused, setHasFocused] = useState(false)
|
|
|
|
const resetAutoFocus = useCallback(() => setHasFocused(false), [])
|
2020-11-26 09:22:30 -05:00
|
|
|
|
2023-05-25 05:59:55 -04:00
|
|
|
// Run on every render but use hasFocused to ensure that the autofocus only
|
|
|
|
// happens once
|
2020-12-15 05:23:54 -05:00
|
|
|
useEffect(() => {
|
2023-05-25 05:59:55 -04:00
|
|
|
if (hasFocused) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
let request: number | null = null
|
2020-12-15 05:23:54 -05:00
|
|
|
if (autoFocusedRef.current) {
|
2023-05-25 05:59:55 -04:00
|
|
|
request = window.requestAnimationFrame(() => {
|
2021-05-18 06:56:56 -04:00
|
|
|
if (autoFocusedRef.current) {
|
|
|
|
autoFocusedRef.current.focus()
|
2023-05-25 05:59:55 -04:00
|
|
|
setHasFocused(true)
|
|
|
|
request = null
|
2021-05-18 06:56:56 -04:00
|
|
|
}
|
2020-12-15 05:23:54 -05:00
|
|
|
})
|
|
|
|
}
|
2020-11-26 09:22:30 -05:00
|
|
|
|
2023-05-25 05:59:55 -04:00
|
|
|
// Cancel a pending autofocus prior to autofocus actually happening on
|
|
|
|
// render, and on unmount
|
|
|
|
return () => {
|
|
|
|
if (request !== null) {
|
|
|
|
window.cancelAnimationFrame(request)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
return { autoFocusedRef, resetAutoFocus }
|
2020-11-26 09:22:30 -05:00
|
|
|
}
|