type AnyFunction = (...args: any[]) => any

function useEvent<T extends AnyFunction>(callback?: T) {
  const ref = useRef<AnyFunction | undefined>(() => {
    throw new Error("Cannot call an event handler while rendering.")
  })
  // Or useInsertionEffect if it's React 18
  useLayoutEffect(() => {
    ref.current = callback
  })
  return useCallback<AnyFunction>((...args) => ref.current?.(...args), []) as T
}

// Usage
function Component(props) {
  const [visible, setVisible] = useState(false)
  // props.onToggle may not be stable
  const onToggle = useEvent(props.onToggle)
  // But our onToggle is stable
  useEffect(() => onToggle(visible), [onToggle, visible])
  // ❌ Throws when used in the render phase
  onToggle(visible)
}