I want to listen for window resize event in react.js. I tried using window.addEventListener but that fires the callback multiple times. Is there a way that the callback runs only once or simply a more react oriented way(a hook maybe) to achieve this?
const resizeQuery = () => {
console.log("check");
if (desktop) setnumberOfShownImages(4);
else if (tablet) setnumberOfShownImages(3);
else if (mobile) setnumberOfShownImages(1);
};
window.addEventListener('resize',resizeQuery);
full Component code:
function ImageSlider(props) {
const [numberOfShownImages, setnumberOfShownImages] = useState(props.numberOfShownImages);
const currentIndex = 0;
const array = [
<PrimaryCard imageHeight = "200" imageAlt = "Fox" imagePath = {fox} header = "Fox" description = "This is a 1"/>,
<PrimaryCard imageHeight = "200" imageAlt = "Fox" imagePath = {fox} header = "Fox" description = "This is a 2"/>,
<PrimaryCard imageHeight = "200" imageAlt = "Fox" imagePath = {fox} header = "Fox" description = "This is a 3"/>,
<PrimaryCard imageHeight = "200" imageAlt = "Fox" imagePath = {fox} header = "Fox" description = "This is a 4"/>,
<PrimaryCard imageHeight = "200" imageAlt = "Fox" imagePath = {fox} header = "Fox" description = "This is a 5"/>,
<PrimaryCard imageHeight = "200" imageAlt = "Fox" imagePath = {fox} header = "Fox" description = "This is a 6"/>,
<PrimaryCard imageHeight = "200" imageAlt = "Fox" imagePath = {fox} header = "Fox" description = "This is a 7"/>,
];
const classes = useStyles();
const theme = useTheme();
const desktop = useMediaQuery(theme.breakpoints.up("lg"));
const tablet = useMediaQuery(theme.breakpoints.up("sm"));
const mobile = useMediaQuery(theme.breakpoints.up("xs"));
const resizeQuery = () => {
console.log("Mahad0");
if (desktop) setnumberOfShownImages(4);
else if (tablet) setnumberOfShownImages(3);
else if (mobile) setnumberOfShownImages(1);
};
window.addEventListener('resize',resizeQuery);
return (
<div className={classes.paper}>
<IconButton aria-label="delete" color="primary">
<ArrowBackIosNewIcon fontSize='large' color='secondary'/>
</IconButton>
{
array.slice(currentIndex, numberOfShownImages)
}
<IconButton aria-label="delete" color="primary">
<ArrowForwardIosIcon fontSize='large' color='secondary'/>
</IconButton>
</div>
)
}
CodePudding user response:
use windowsize hook
import { useState, useEffect } from "react";
// Usage
function App() {
const size = useWindowSize();
return (
<div>
{size.width}px / {size.height}px
</div>
);
}
// Hook
function useWindowSize() {
// Initialize state with undefined width/height so server and client renders match
// Learn more here: https://joshwcomeau.com/react/the-perils-of-rehydration/
const [windowSize, setWindowSize] = useState({
width: undefined,
height: undefined,
});
useEffect(() => {
// Handler to call on window resize
function handleResize() {
// Set window width/height to state
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
}
// Add event listener
window.addEventListener("resize", handleResize);
// Call handler right away so state gets updated with initial window size
handleResize();
// Remove event listener on cleanup
return () => window.removeEventListener("resize", handleResize);
}, []); // Empty array ensures that effect is only run on mount
return windowSize;
}