Home > Back-end >  React Hook "React.useEffect" is called conditionally
React Hook "React.useEffect" is called conditionally

Time:09-01

I have a hook inside my component, which detects when I am scrolling down or up. This is the code :

const [scrollDirection, setScrollDirection] = React.useState('')
    const [prevOffset, setPrevOffset] = React.useState(0)
    const {width} = useWindowSize()
    const useScrollDirection = () => {
        if (typeof window !== 'undefined') {
        const nav = document.querySelector('.nav');

        const toggleScrollDirection = () => {
           let scrollY = window.scrollY
           if (scrollY === 0) {
               setScrollDirection('')
           }
           if (scrollY > prevOffset) {
               nav?.classList.remove('activee')
           } else if (scrollY < prevOffset) {
            nav?.classList.add('activee')
           }
           setPrevOffset(scrollY)
        }
        React.useEffect(() => {
            window.addEventListener("scroll", toggleScrollDirection)
            return () => {
                window.removeEventListener("scroll", toggleScrollDirection)
            }
        })
        return scrollDirection
    }
    }
    React.useEffect(() =>
    {
        
        if(width<600) {
            setMobile(true)
        }
        else setMobile(false)
    }, [width])

    useScrollDirection()

Eventually when I try to build the site, I get an error " React Hook "React.useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return? react-hooks/rules-of-hooks". I wonder why is this happening ? any idea to fix this ? Thanks.

CodePudding user response:

The error is pretty self descriptive:

React Hook "React.useEffect" is called conditionally.
React Hooks must be called in the exact same order in every component render.
Did you accidentally call a React Hook after an early return?

Documentation: https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

useEffect cannot be called within a function that is declared within a component. useEffect and other hooks must always be called in the exact same order every time a function is executed.

For your useScrollDirection function, you are declaring a hook (which is fine) but then you are using useEffect within the hook. The declaration of useScrollDirection must be moved to be outside of the component in order to use useEffect inside of it.

const useScrollDirection = () => {
  // ...
  useEffect(() => {
    // ...
  }, []);
};

const Component = () => {
  useScrollDirection();
}
  • Related