Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

109
Views
Sticky header with hide and show on scroll

I have a navbar with two part (navbarTop and navbarBottom); navbarTop will shown when the scrollY is bigger than 110 and the navbarbottom will shown when the user scroll up, but my problem is that each component will be re-called after each scroll, even scrolling down, or when the navbottom already exist and the user scroll up and it's still keep calling the component. here is the code:

const Navbar: FC = () => {

const [stickyHeader, setStickyHeader] = useState(false);
const [stickyMenu, setStickyMenu] = useState(false);

console.log('navbar')

const [y, setY] = useState(null);
const handleNavigation = useCallback(
    (e) => {
        const window = e.currentTarget;
        if (!stickyMenu) {
            if (y > window.scrollY) {
                setStickyMenu(true)
                // console.log("scrolling up");
            }
        }
        if (!stickyHeader) {
            if (window.scrollY >= 110) {
                setStickyHeader(true);
            }
        }
        if (stickyHeader) {
            if (window.scrollY <= 110) {
                setStickyHeader(false);
            }
        }
        if (stickyMenu) {
            if (y < window.scrollY) {
                setStickyMenu(false)
                // console.log("scrolling down");
            }
        }

        setY(window.scrollY);
    },
    [y, stickyMenu,stickyHeader]
);


useEffect(() => {
    window.addEventListener("scroll", handleNavigation);

    return () => {
        window.removeEventListener("scroll", handleNavigation);
    };
}, [handleNavigation, stickyMenu]);



return (
    <>
        <div className={s.root}>

            {stickyHeader === false ? (
                <div className='hidden xl:block md:w-auto'>
                    <NavbarTop sticky={false}/>
                    <NavbarBottom
                        sticky={false}/>
                </div>
            ) : (
                <div className='absolute hidden xl:block md:w-auto'>
                    <NavbarTop sticky={true}/>
                    {stickyMenu &&
                        <NavbarBottom sticky={true}/>
                    }
                </div>
            )}

            <SmallNav/>
        </div>
    </>

)

} export default Navbar

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

In fact, I did not quite understand your question. You said that each component is re-called after each scroll. Of course it will be re-called, right?

Whenever you scroll, you change the stickyHeader or stickyMenu. React listens for the state change and re-renders the component. This is how React works.

I see that you're using tailwindcss.

You can use a useMemo to listen to the state and then return the appropriate class based on the different state states. This way you avoid having to create DOM nodes over and over again. I don't know if this would help you or not. I hope this will help you.

const Navbar: FC = () => {
    const [stickyHeader, setStickyHeader] = useState(false);
    const [stickyMenu, setStickyMenu] = useState(false);
    // console.log('navbar');

    const [y, setY] = useState(null);
    const handleNavigation = useCallback(
        (e) => {
            const window = e.currentTarget;
            if (!stickyMenu) {
                if (y > window.scrollY) {
                    setStickyMenu(true);
                    // console.log("scrolling up");
                }
            }
            if (!stickyHeader) {
                if (window.scrollY >= 110) {
                    setStickyHeader(true);
                }
            }
            if (stickyHeader) {
                if (window.scrollY <= 110) {
                    setStickyHeader(false);
                }
            }
            if (stickyMenu) {
                if (y < window.scrollY) {
                    setStickyMenu(false);
                    // console.log("scrolling down");
                }
            }

            setY(window.scrollY);
        },
        [y, stickyMenu, stickyHeader],
    );

    useEffect(() => {
        window.addEventListener('scroll', handleNavigation);

        return () => {
            window.removeEventListener('scroll', handleNavigation);
        };
    }, [handleNavigation, stickyMenu]);

    const stickyClassName = useMemo(() => {
        if (stickyHeader) {
            return 'sticky top-0 xl:block md:w-auto';
        }
        return 'xl:block md:w-auto';
    }, [stickyHeader]);

    return (
        <div className="test" style={{ height: 2000 }}>
            <div className={stickyClassName}>
                <NavbarTop sticky={stickyHeader} />
                {stickyMenu && <NavbarBottom sticky={stickyHeader} />}
            </div>
            <div>SmallNav</div>
        </div>
    );
};

export default Navbar;
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!