[英]React and setTimeout/setInterval causing render issues
I am quite new to React, learning it for 1 year, but I stuck with the simple slideshow component.我对 React 很陌生,学习了 1 年,但我坚持使用简单的幻灯片组件。 I have to display images in a 2 seconds interval, but it causes the background to clip or rather re-render when scrolling.我必须以 2 秒的间隔显示图像,但这会导致背景在滚动时被剪辑或重新渲染。 I have to solve it, which means I must use some sort of autoplay and still not break the page.我必须解决它,这意味着我必须使用某种自动播放并且仍然不会破坏页面。 I attach the code and a GIF that shows my issue and it can be seen that a background-colored row appears above the image slideshow.我附上了显示我的问题的代码和 GIF,可以看到图像幻灯片上方出现了一个背景色的行。 Also when I removed the whole component the page did not produce this rendering issue.此外,当我删除整个组件时,页面也没有产生这个渲染问题。 Please I really need some help regarding this problem, I am hoping somebody who is more experienced with React can tell me how to approach this.关于这个问题,我真的需要一些帮助,我希望对 React 更有经验的人可以告诉我如何解决这个问题。 The slideshow component:幻灯片组件:
import React, { useState, useEffect } from "react";
import { hands } from "../../../../assets/images/landing_hands/index.js";
import { AnimatePresence, motion } from "framer-motion";
const ImageSlideShow = () => {
const [slideShowInterval, setSlideShowInterval] = useState(null);
const [activeImage, setActiveImage] = useState(0);
const DURATION = 2000;
const killAutoPlay = () => {
console.log("killing interval");
clearInterval(slideShowInterval);
setSlideShowInterval(null);
};
const startAutoPlay = () => {
if (slideShowInterval === null) {
console.log("starting interval");
const int = setInterval(() => {
setActiveImage((prev) => {
let nextIndex = prev + 1;
if (nextIndex >= hands.length) {
return 0;
} else return nextIndex;
});
}, DURATION);
setSlideShowInterval(int);
}
};
useEffect(() => {
document.addEventListener(
"visibilitychange",
() => {
console.log(document.visibilityState);
if (document.visibilityState === "hidden") {
killAutoPlay();
} else {
startAutoPlay();
}
},
false
);
return () => {
document.removeEventListener("visibilitychange", () => {});
};
}, []);
return (
<AnimatePresence>
<motion.img
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
src={hands[activeImage]}
alt={"nft"}
/>
</AnimatePresence>
);
};
export default ImageSlideShow;
GIF: https://lh4.googleusercontent.com/t_dQ7NqHxHfcZJzd-FV00Sg2NaBd5nZ1uaUohFafnL06qyx5bFQRIgPHBHJwZkeQva8=w2400 GIF: https://lh4.googleusercontent.com/t_dQ7NqHxHfcZJzd-FV00Sg2NaBd5nZ1uaUohFafnL06qyx5bFQRIgPHBHJwZkeQva8=w2400
I appreciate all your effort and answers.我感谢您的所有努力和回答。
I updated the code with Sergey Sosunov's approach, still getting the rendering glitch, deplyed the app to Vercel and made the repository public.我用 Sergey Sosunov 的方法更新了代码,仍然出现渲染故障,将应用程序部署到 Vercel 并将存储库公开。 https://vercel.com/zsoltgombocz/cwp-new https://github.com/zsoltgombocz/cwp-new https://vercel.com/zsoltgombocz/cwp-new https://github.com/zsoltgombocz/cwp-new
Also after the new code added to the project, I captured the screen to show how the purple backgroud glitches through the image slideshow.同样在将新代码添加到项目之后,我捕获了屏幕以显示紫色背景如何通过图像幻灯片出现故障。 https://lh6.googleusercontent.com/fhqqH5SOOt-PbM4K03qADwQEJKNg_fXR-IU1iCdbD7gXUx2F5TKKnluo6aUenEQFZnE=w2400 https://lh6.googleusercontent.com/fhqqH5SOOt-PbM4K03qADwQEJKNg_fXR-IU1iCdbD7gXUx2F5TKKnluo6aUenEQFZnE=w2400
I tried to reproduce your issue but the only thing i faced was multiple setTimeouts execution.我试图重现您的问题,但我唯一面临的是多次 setTimeouts 执行。 Your document.removeEventListener
is invalid and does not work as expected, also, things should be done much more easier than you did.您的document.removeEventListener
无效并且无法按预期工作,而且,事情应该比您做的更容易。
import { useState, useEffect } from "react";
import { hands } from "./hands";
import "./styles.css";
import { AnimatePresence, motion } from "framer-motion";
export default function App() {
return (
<div className="App">
<ImageSlideShow />
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
const ImageSlideShow = () => {
const DURATION = 2000;
const [isVisible, setIsVisible] = useState(true);
const [activeImage, setActiveImage] = useState(0);
useEffect(() => {
if (!isVisible) return;
const intervalId = setInterval(() => {
setActiveImage((prev) => {
const next = prev + 1;
return next >= hands.length ? 0 : next;
});
}, DURATION);
return () => clearInterval(intervalId);
}, [isVisible]);
useEffect(() => {
const onVisibilityChange = () => {
console.log(document.visibilityState);
setIsVisible(document.visibilityState !== "hidden");
};
document.addEventListener("visibilitychange", onVisibilityChange);
return () => {
document.removeEventListener("visibilitychange", onVisibilityChange);
};
}, []);
return (
<AnimatePresence>
<motion.img
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
src={hands[activeImage]}
alt={"nft"}
/>
</AnimatePresence>
);
};
Try to change your code to this one and tell if issue still exists.尝试将您的代码更改为此代码并判断问题是否仍然存在。 If yes - i honestly dont know how to help until you provide a way to reproduce it.如果是的话 - 我真的不知道如何提供帮助,直到您提供一种重现它的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.