我正在构建一个具有滑动图像库的组件。基本想法是我有一堆图像,带有
index=== stateIndex
的图像将应用一个活动类。每张图片都会显示一段时间,然后stateIndex
就会更新。
但是,我无法让上下文状态相应更新。我正在使用功能状态更新,因此状态不应滞后。我以前从未使用过
setInterval
函数,所以不确定这是否是问题所在,或者我是否只是在某个地方遇到了一个简单的错误。
在上面的示例中,单击播放按钮应该会导致图像框以不同的时间间隔在索引 0-4 之间循环。
我有从上下文导入以下对象。
const [videoOptions, setVideoOptions] = useState({
currentIndex: null,
isPlaying: false,
intervalId: null,
startTime: 0,
elapsedTime: 0,
segmentDurations: [2, 3, 6, 13],
imgPaths: ["1", "2", "3", "4"],
});
我的组件有一个简单的框和播放按钮:
<div className='App'>
<h1>Hello React.</h1>
<div className="image-container">
{videoOptions.imgPaths.map((path, index) => {
return (
<div
key={index}
src={path}
className={`panning-image ${videoOptions.currentIndex === index ? "active" : ""}`}
>{index}</div>
);
})}
</div>
<button
id="play-button"
className="icon-button"
onClick={handlePlayClick}
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M8 5v14l11-7z" />
</svg>
</button>
</div>
这些功能相当简单,我只需要适当更新我的状态值即可。
const { setVideoOptions, videoOptions } =
useContext(AppContext);
const [intervalId, setIntervalId]= useState(null)
function handlePlayClick() {
if (!videoOptions.isPlaying) {
startSlideshow();
}
}
function startSlideshow(
) {
const images = document.querySelectorAll(".panning-image");
if (images.length > 0) {
console.log('click')
setVideoOptions((prev) => ({
...prev,
currentIndex: 0,
isPlaying: true,
}));
console.log(videoOptions);
// Calculate remaining duration for the current segment
let remainingDuration =
videoOptions.segmentDurations[videoOptions.currentIndex || 0] -
videoOptions.elapsedTime;
console.log(videoOptions);
const newIntervalId = setInterval(() => {
goToNextImage();
}, remainingDuration * 1000);
setIntervalId(newIntervalId)
}
}
function goToNextImage() {
const nextIndex = getNextIndex(
videoOptions.currentIndex,
videoOptions.imgPaths.length
);
console.log("running", nextIndex);
clearInterval(intervalId);
setVideoOptions((prev) => ({
...prev,
currentIndex: nextIndex,
elapsedTime: 0,
}));
}
控制台日志表明
videoOptions.currentIndex
始终为空。
useEffect(() => {
return () => clearInterval(intervalId);
}, [intervalId]);
setVideoOptions((prev) => ({
...prev,
currentIndex: 0,
isPlaying: true,
}));
setVideoOptions((prev) => {
const nextIndex = getNextIndex(prev.currentIndex, prev.imgPaths.length);
console.log("running", nextIndex);
// Clear previous interval
clearInterval(intervalId);
const newIntervalId = setInterval(() => {
goToNextImage();
}, prev.segmentDurations[nextIndex] * 1000);
setIntervalId(newIntervalId);
return {
...prev,
currentIndex: nextIndex,
elapsedTime: 0,
};
});
const newIntervalId = setInterval(() => {
goToNextImage();
}, prev.segmentDurations[nextIndex] * 1000);
setIntervalId(newIntervalId);
我确保正确处理滑动图库的状态更新和间隔管理。第一步是添加一个 useEffect 挂钩,该挂钩在组件卸载或 IntervalId 更改时清理间隔,从而防止潜在的内存泄漏。然后,我修改了 startSlideshow 函数,将 currentIndex 初始化为 0,并在开始幻灯片放映时将 isPlaying 设置为 true。这可以确保第一张图像正确显示。我还调整了 goToNextImage 函数以使用 setVideoOptions 中的功能更新,确保状态根据之前的状态正确更新。这有助于捕获间隔回调内的最新状态。此外,我通过清除之前的间隔并在 goToNextImage 中设置新的间隔来管理间隔,确保幻灯片以每个图像片段的正确时间继续播放。这些更改共同确保状态正确更新,并且幻灯片以指定的时间间隔循环显示图像,从而提供预期的功能