Files
dify/web/hooks/use-stable-handler-only-when-you-know-what-you-are-doing-or-you-will-be-fired.ts
BrianWang1990 9308287fea fix: copy button not working on API Server and API Key pages (#34515)
Co-authored-by: Brian Wang <BrianWang1990@users.noreply.github.com>
Co-authored-by: test <test@testdeMac-mini.local>
Co-authored-by: BrianWang1990 <512dabing99@163.com>
Co-authored-by: Stephen Zhou <hi@hyoban.cc>
Co-authored-by: Stephen Zhou <38493346+hyoban@users.noreply.github.com>
2026-04-09 02:49:40 +00:00

45 lines
1.5 KiB
TypeScript

import * as reactExports from 'react'
import { useCallback, useEffect, useLayoutEffect, useRef } from 'react'
// useIsomorphicInsertionEffect
const useInsertionEffect
= typeof window === 'undefined'
// useInsertionEffect is only available in React 18+
? useEffect
: reactExports.useInsertionEffect || useLayoutEffect
/**
* @see https://foxact.skk.moe/use-stable-handler-only-when-you-know-what-you-are-doing-or-you-will-be-fired
* Similar to useCallback, with a few subtle differences:
* - The returned function is a stable reference, and will always be the same between renders
* - No dependency lists required
* - Properties or state accessed within the callback will always be "current"
*/
// eslint-disable-next-line ts/no-explicit-any
export function useStableHandler<Args extends any[], Result>(
callback: (...args: Args) => Result,
): typeof callback {
// Keep track of the latest callback:
// eslint-disable-next-line ts/no-explicit-any
const latestRef = useRef<typeof callback>(shouldNotBeInvokedBeforeMount as any)
useInsertionEffect(() => {
latestRef.current = callback
}, [callback])
return useCallback<typeof callback>((...args) => {
const fn = latestRef.current
return fn(...args)
}, [])
}
/**
* Render methods should be pure, especially when concurrency is used,
* so we will throw this error if the callback is called while rendering.
*/
function shouldNotBeInvokedBeforeMount() {
throw new Error(
'foxact: the stablized handler cannot be invoked before the component has mounted.',
)
}