Created
November 12, 2019 13:54
-
-
Save rolandcoops/4364be2eff3586b0f8f3d0c10dc3be61 to your computer and use it in GitHub Desktop.
Custom React hook for creating a stable callback reference that can be passed down as prop
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Taken (with some minor changes) from: | |
// https://reactjs.org/docs/hooks-faq.html#how-to-read-an-often-changing-value-from-usecallback | |
import { useRef, useEffect, useCallback } from 'react' | |
const throwReferenceError = () => { | |
throw new ReferenceError('Callback was called directly while rendering, pass it as a callback prop instead.') | |
} | |
/** | |
* Custom hook that wraps an unstable callback inside a stable wrapper callback. | |
* Useful to e.g. keep an event handler prop stable when passing it down. | |
* | |
* @param {Function} callback - unstable callback to be wrapped | |
* @param {Array} deps - list of values whose change will update the unstable callback reference (see React.useCallback) | |
* @returns {Function} stable wrapped callback | |
* | |
* @example | |
* // `handleClick` reference will not change even if deps change: | |
* const handleClick = useStableCallback((event) => { | |
* console.log(someDep, event.target) | |
* }, [someDep]) | |
*/ | |
const useStableCallback = (callback, deps) => { | |
const ref = useRef(throwReferenceError) | |
// update stored callback ref if callback or deps change | |
useEffect(() => { | |
ref.current = callback | |
// eslint-disable-next-line react-hooks/exhaustive-deps | |
}, [callback, ...deps]) | |
// return stable wrapped callback | |
return useCallback((...args) => { | |
ref.current(...args) | |
}, [ref]) | |
} | |
export default useStableCallback |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment