Skip to content

Instantly share code, notes, and snippets.

@crazy4groovy
Forked from diegohaz/useEvent.tsx
Last active May 19, 2022 20:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crazy4groovy/28318a0cdb1bbeefb687e958bee66917 to your computer and use it in GitHub Desktop.
Save crazy4groovy/28318a0cdb1bbeefb687e958bee66917 to your computer and use it in GitHub Desktop.
Make a component callback prop stable (i.e. cannot be used during render phase) (ReactJS)
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.")
})
useLayoutEffect(() => {
ref.current = callback
})
return useCallback<AnyFunction>(
(...args) => ref.current?.apply(null, 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)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment