I want to change background color of navigation gradually with transition like this
Article.js
import React, { useRef, useEffect } from 'react';
import Grid from '@mui/material/Grid';
import { Link as RouterLink } from "react-router-dom";
import Typography from '@mui/material/Typography';
import Breadcrumbs from '@mui/material/Breadcrumbs';
import Link from '@mui/material/Link';
import './Article.css';
export default function Article() {
const [isScrolling, setScrolling] = React.useState(false);
useEffect(() => {
function handleScroll() {
if (window.scrollY < 10) {
setScrolling(false);
} else {
setScrolling(true);
}
}
window.addEventListener("scroll", handleScroll, { passive: true });
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, [isScrolling]);
function CreateBasicBreadcrumbs() {
return (
<div
role="presentation"
className={`pop-up ${isScrolling && 'active'}`}
>
<Breadcrumbs
aria-label="breadcrumb"
sx={{ marginLeft: 2, }}
>
<Link
underline="hover"
color="inherit"
component={RouterLink}
to={'/'}
>
Home
</Link>
<Typography color="text.primary">
Articles
</Typography>
</Breadcrumbs>
</div >
);
}
return (
<Grid
container='true'
direction='row'
width='100%'
sx={{
paddingTop: 5,
backgroundColor: 'rgb(248, 249, 250)'
}}
onScroll={(e) => { console.log('scrolling') }}
>
<Grid
item='true'
xs={12}
sm={12}
md={12}
lg={9}
xl={7}
sx={{
paddingLeft: 5,
height: '2000px',
}}
>
<CreateBasicBreadcrumbs />
</Grid>
</Grid>
);
}
Article.css
.pop-up {
padding-bottom: 20px;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
position: sticky;
top: 10px;
transition: all 1s linear;
}
.pop-up.active {
background-color: rgb(255, 255, 255);
}
When I run these, class name ‘active’ is added to the [div] but its background color is changed quickly from rgb(248, 249, 250) to rgb(255, 255, 255).
I think this is because addEventListener changes isScrolling every scroll and rerenders the [div] element and its children. But I’m not sure.
Could you tell me what I am doing wrong?
Advertisement
Answer
You should not define a Component like CreateBasicBreadcrumbs inside another component. If you do so, React thinks it is a different object on every render of Article, so CreateBasicBreadcrumbs will be unmounted before every rerender of Article, losing its state.
Simply move its definition outside Article, and pass isScrolling as prop down to it.