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();
}