Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

110
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda