'how to use a styled component to play an animation on scroll in react

I've been trying to use styled-component animations to make my navbar change color upon scrolling down and returning it to the original color when I scroll back up. the only issue I'm currently facing is that I have no idea how to only trigger it when you scroll down the page and return it back to normal when I hit the top again.

const ChangeColor = keyframes`
0%{
  background-color: #121314;
}
100%{
    background-color: white;
}
`;

const GeneralContainer = styled.body`
  background-color: #121314;
  height: 10000px;

  margin: 0;
`;

const NavBarContainer = styled.div`
  border: 1px green solid;
  height: 64px;
  position: fixed;
  width: 100%;
  animation: ${NavForward} 1s linear alternate forwards 1; //I just want this to fire once when I scroll downward and fire again when I return to the top of the page.
`;

export default function Home() {
  const [offset, setOffset] = useState(0);
  const [isUpper, setIsUpper] = useState(true); // was trying to use this to trigger but couldnt

  useEffect(() => {
    const onScroll = () => {
      setOffset(window.pageYOffset);
      if (window.pageYOffset > 30 && isUpper === true) {
        setIsUpper(false);
      } else if (window.pageYOffset <= 30 && isUpper === false) {
        setIsUpper(true);
      }
    };
    // clean up code
    window.removeEventListener("scroll", onScroll);
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  return (
    <GeneralContainer>
      <NavBarContainer
        isUpper={isUpper}
        scoll={offset}
      ></NavBarContainer>
    </GeneralContainer>
  );
}


Solution 1:[1]

You could do something like this:

// Get a hook function
const {
  useState,
  useEffect
} = React;

const Home = () => {
  const [offset, setOffset] = useState(0);
  const [isUpper, setIsUpper] = useState(true); // was trying to use this to trigger but couldnt

  useEffect(() => {
    const onScroll = () => {
      setOffset(window.pageYOffset);
      if (window.pageYOffset > 30) {
        setIsUpper(false);
      } else if (window.pageYOffset <= 30) {
        setIsUpper(true);
      }
    };
    // clean up code
    window.removeEventListener("scroll", onScroll);
    window.addEventListener("scroll", onScroll, {
      passive: true
    });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  return ( <nav className ={isUpper ? 'top' : ''} > < /nav>
  );
};

// Render it
ReactDOM.render( <
  Home / > ,
  document.getElementById("react")
);
body {
  height: 2000px;
}

nav {
  height: 50px;
  position: fixed;
  top: 0;
  width: 100%;
  background-color: red;
  transition: background-color 1s ease;
}

nav.top {
  background-color: blue;
  transition: background-color 1s ease;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Charlie Araya