When passing callbacks to child components to detect their changes, you may need to call the callbacks inside useEffect
or useLayoutEffect
and add the callbacks into its dependency array:
useLayoutEffect(() => {
if(onScroll) onScroll(x, pos) // call the callback
}, [x, pos, onScroll])
However, this will cause an infinite loop when rendering if the callback will trigger the re-render of the parent component--even if it is just setting some states.
const onScroll = (x, y) => {
setScroll([x, y])
}
The onScroll
function(object) will be recreated in every re-render, consequently triggering the calling of itself since it's in the dependency list, and going on and on......boom.
You can simply remove the callback from the dependency list to fix the problem, but you will get the react-hooks/exhaustive-deps
warning if you're using the lint.
Another solution is to use useCallback
to memorize the callback function to prevent it from being recreated.
const [scroll, setScroll] = useState([0, 0]
...
const onScroll = useCallback((x, y) => {
setScroll([x, y])
}, [setScroll])
According to official doc, the state setting function created by setState
won’t change on re-renders, so it can be used in the dependency list to retain the identity of the callback function.
Top comments (0)