Search code examples
javascriptreactjsreact-hooksuse-effect

Why doesn't useEffect hook work as expected?


I've never used hooks in React and I'm trying to use useEffect() but I don't seem to get the basics of its correct structure and use.

I was able to achieve the results with plain JavaScript but with useState the state remains untouched.

Then I found useEffect after searching for a while, and this is what I could get it to look like-

// Background Parallax Effect

let [translateY,setTranslateY] = useState(0);
useEffect(()=> {
    const getScrollPos = ()=> {
        setTranslateY(window.scrollY*(-.2));

        requestAnimationFrame(getScrollPos);
    }

    document.addEventListener("DOMContentLoaded",getScrollPos)
},[translateY]);

I highly suspect that its structure isn't as it is supposed to be.

So I want to know the fixes and how it exactly works to help understand the structure better.


Solution

  • The issue with your first code is that you add translateY as a dependency to useEffect. . You should remove translateY as a dependency and also remove the event listener when the component unmounts. Also you have a requestAnimationCallback within the getScrollPos function which is triggered unconditionally causing infinite loop

    useEffect(()=> {
        const getScrollPos = ()=> {
            setTranslateY(window.scrollY*(-.2));
        }
        const setScrollPos = () => {
           requestAnimationFrame(getScrollPos);
        }
    
        document.addEventListener("DOMContentLoaded",setScrollPos);
    
        return () => {
            document.removeEventListener("DOMContentLoaded",setScrollPos)
        }
    },[]);
    

    Note that if you update the state with same value, react prevents a re-render.

    In the second code, although you call the state update by using listenScroll directly in render function, it doesn't cause a loop because you would be setting the same value to update state and hence an infinite loop doesn't occur