问题
I'm trying to make a Sticky Header that can change its background-color based on his position on the page. To do that, I'm trying to add a className "active" to my Styled Component "StyledHeader" that will appears when the scrollPositionY is above 400px and disappear when below.
In other words, what I want to do is something like this but using React.JS, JSX syntax and Styled Components.
Here's what I have for now:
import { Link } from '@reach/router';
import DuskLogo from '../images/dusk_logo.svg';
import {
StyledHeader,
StyledDuskLogo
} from '../styles/StyledHeader';
const Header = () => (
<StyledHeader>
<div className="header-content">
<Link to="/">
<StyledDuskLogo src={DuskLogo} alt="dusk-logo" />
</Link>
</div>
</StyledHeader>
)
export default Header;
Do you know a simple way to do it ?
回答1:
add an event listener in your useEffect
. when you scroll down the value of window.scrollY
will increase such as 1, 2, ...100 .. (in px) and update your color
in useState
as per the window.scrollY. try something like this
const StyledBody = window.styled.div`
background: lightgray;
height: 5000px;
`;
const StyledText = window.styled.h4`
text-align: center;
width: 250px;
margin: auto;
line-height: 40px;
`;
const StyledHeader = window.styled.div`
background-color: ${props => props.color};
width: 100%;
height: auto;
position: fixed;
top: 0;
left: 0;
right: 0px;
padding: 0;
z-index: 10000;
transition: all 1s ease-in-out;
`;
const Header = () => {
const [color, setColor] = React.useState("rgba(17, 42, 107, 0.7)");
const handleScroll = React.useCallback((event) => {
let scrollTop = window.scrollY;
//console.log(scrollTop ); //1,2,...100,...200...etc (in px)
if (scrollTop >= 20 && scrollTop < 50) {
setColor("yellow");
}
if (scrollTop >= 50 && scrollTop < 90) {
setColor("red");
}
if (scrollTop >= 90 && scrollTop < 120) {
setColor("green");
}
if (scrollTop >= 120 && scrollTop < 150) {
setColor("blue");
}
if (scrollTop >= 150 && scrollTop < 180) {
setColor("violet");
}
if (scrollTop >= 180 && scrollTop < 210) {
setColor("purple");
}
});
React.useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll, false);
};
}, []);
return (
<StyledBody>
<StyledHeader color={color}>
<StyledText>My background color changes</StyledText>
</StyledHeader>
</StyledBody>
);
};
export default Header;
here is a working demo ..change the code as per your need.demo
Edit: I have added styled-components for you. check it out and let me know whether it works for you. to know more about these hooks go to useEffect and useCallback
回答2:
haven't run this code myself but could be something like:
const Header = () => {
const headerEl = React.useRef();
const [offsetTop, setOffsetTop] = React.useState(0);
React.useEffect(() => {
window.addEventListener("scroll", onScroll, false);
return () => {
window.removeEventListener("scroll", onScroll, false); // to remove scroll event on unmount
};
}, []);
const onScroll = () => setOffsetTop(headerEl.current.offsetTop);
return (
<StyledHeader ref={headerEl} className={offsetTop > 400 ? "active" : ""}>
...
</StyledHeader>
);
};
export default Header;
来源:https://stackoverflow.com/questions/58555762/how-to-add-a-classname-and-remove-it-onscroll-event-in-react-js