简体   繁体   中英

How do I prevent window.pageYOffset from resetting on render?

I have a react component where I want to change the header based on the scroll event. I'm attaching an event handler and based on scroll position and toggling a display class to hide ro show the desired elements.

Where I'm having trouble is, there seems to be some glitchy behavior when my component tries to re render. I have an example in codesandbox below.

import React from "react";
import "./styles.css";

export default function App() {
  const [scrollY, setScrollY] = React.useState(0);
  React.useEffect(() => {
    const handleScroll = () => {
      console.log(window.pageYOffset);
      setScrollY(window.pageYOffset);
    };

    window.addEventListener("scroll", handleScroll, { passive: true });
    return () => window.removeEventListener("scroll", handleScroll);
  }, [setScrollY]);

  const scrolled = () => scrollY > 40;

  return (
    <div className="App">
      <div className={`header ${scrolled() ? "d-none" : ""}`}>Header Main</div>
      <div>
        <div className={`header-secondary ${scrolled() ? "d-none" : ""}`}>
          Header Secondary
        </div>
        <div className={`header-scrolled ${!scrolled() ? "d-none" : ""}`}>
          HeaderScrolled
        </div>

        <div>Scroll Position: {scrollY}</div>
        {[...Array(100)].map((e, i) => (
          <div>
            <div className={scrolled()}>{`SCROLLING`}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

My code sandbox: https://codesandbox.io/s/wizardly-saha-0oklr

If you notice I have my hide/unhide compnent condition set at 40px. When you scroll slowly around 40px the header will snap back and for some reason the window.pageYOffset will reset to 0. I can't figure out why this is?

If you scroll past fast enough it doesn't matter but right around where I toggle the display class there is some odd behavior.

EDIT : Updated Example Effectively what I need to do is have a smmoth transition from Header Main to Header Secondary . I can't really change styling on Header Main because I don't own that part of the product.

The problem is about your header. When you are at the top header affects the height of the scrolling body because it is position relative. When you start to scroll down it becomes fixed and leaves the body so it doesn't affect. When you scroll back to top it affect scroll height again.

So there are some tricks to resolve this issue. Giving padding-top: 50px; to scrolling element and using header always fixed will save you.

.App {
  padding-top: 50px;
}


.header {
  width: 100%;
  height: 50px;
  background-color: teal;
  position: fixed;
  top: 0;
}

.header-scrolled {
  width: 100%;
  height: 50px;
  background-color: green;
  color: white;
  position: fixed;
  top: 0;
}

https://codesandbox.io/s/lingering-pine-puunf

I was having the exact same issue for two days. The fix I implemented was to render a "sticky-nav" component in addition to the original "nav" component. This way the original nav will still exist on top (but above the visible window so you'd never know) and when you scroll down the "sticky-nav" appears. Since the original nav is always there and doesn't change position, it won't affect the scroll position and cause the glitch when slowly scrolling back up.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM