使用 React hooks 和 setInterval 的幻灯片
Slideshow using React hooks and setInterval
我正在尝试使用 React Hooks 和 setInterval 制作包含 5 张图片的幻灯片。
所以当计数器到达照片 5(索引 4)时,它返回到照片 1(索引 0)。
计数器看起来没问题,但是当 if 语句中的条件为假时,计数器会一直计数到 4。
import React, { useState, useEffect } from 'react';
import { photoSource } from './photo-source.js';
function Slideshow() {
const [imgSource, setImgSource] = useState(0);
useEffect(() => {
const intervalId = setInterval(() => {
if (imgSource <= 1) {
setImgSource(imgSource => imgSource + 1);
} else {
setImgSource(0);
}
}, 10000);
return () => clearInterval(intervalId);
}, []);
console.log('ImgSource: ' + imgSource);
console.log(imgSource <= 1)
console.log(photoSource[imgSource].src)
记录到控制台的所有值似乎都是正确的,唯一明显的问题是计数器一直在计数,就好像 if 语句不起作用一样。
这里有两个问题。 First 很小:条件应该是 imgSource < 4
,而不是 imgSource <= 1
。其次,更重要的是,setImgSource
之外的 imgSource
的值被锁定在调用 setInterval
时的值(锁定为零)。因此,条件始终为真,因为 imgSource
是 0
,并且该值继续递增超过目标最大值 4
。
有几种方法可以处理这个问题,其中最简单的方法是在 setImgSource
回调中执行检查,因为它可以访问 imgSource
的当前值。
例如:
useEffect(() => {
const intervalId = setInterval(() => {
setImgSource((imgSource) => {
if (imgSource < 4) {
return imgSource + 1;
}
return 0;
});
}, 10000);
return () => clearInterval(intervalId);
}, []);
尽管您可以使用 %
(余数)运算符删除一些代码,如下所示:
useEffect(() => {
const intervalId = setInterval(() => {
setImgSource((imgSource) => (imgSource + 1) % 5);
}, 1000);
return () => clearInterval(intervalId);
}, []);
请注意,在 JavaScript 中,%
运算符计算余数,而不是 modulus。这两个对于正数是相同的,所以这种方法会起作用,因为你只是递增 imgSource
。如果您希望幻灯片放映改变方向,您必须做更多的工作才能使相同的方法起作用,这里有一个 mod 函数:
export function mod(n, m) {
return ((n % m) + m) % m;
}
你可以这样使用:
setImgSource(prev => mod(prev + 1, 5));
我正在尝试使用 React Hooks 和 setInterval 制作包含 5 张图片的幻灯片。
所以当计数器到达照片 5(索引 4)时,它返回到照片 1(索引 0)。
计数器看起来没问题,但是当 if 语句中的条件为假时,计数器会一直计数到 4。
import React, { useState, useEffect } from 'react';
import { photoSource } from './photo-source.js';
function Slideshow() {
const [imgSource, setImgSource] = useState(0);
useEffect(() => {
const intervalId = setInterval(() => {
if (imgSource <= 1) {
setImgSource(imgSource => imgSource + 1);
} else {
setImgSource(0);
}
}, 10000);
return () => clearInterval(intervalId);
}, []);
console.log('ImgSource: ' + imgSource);
console.log(imgSource <= 1)
console.log(photoSource[imgSource].src)
记录到控制台的所有值似乎都是正确的,唯一明显的问题是计数器一直在计数,就好像 if 语句不起作用一样。
这里有两个问题。 First 很小:条件应该是 imgSource < 4
,而不是 imgSource <= 1
。其次,更重要的是,setImgSource
之外的 imgSource
的值被锁定在调用 setInterval
时的值(锁定为零)。因此,条件始终为真,因为 imgSource
是 0
,并且该值继续递增超过目标最大值 4
。
有几种方法可以处理这个问题,其中最简单的方法是在 setImgSource
回调中执行检查,因为它可以访问 imgSource
的当前值。
例如:
useEffect(() => {
const intervalId = setInterval(() => {
setImgSource((imgSource) => {
if (imgSource < 4) {
return imgSource + 1;
}
return 0;
});
}, 10000);
return () => clearInterval(intervalId);
}, []);
尽管您可以使用 %
(余数)运算符删除一些代码,如下所示:
useEffect(() => {
const intervalId = setInterval(() => {
setImgSource((imgSource) => (imgSource + 1) % 5);
}, 1000);
return () => clearInterval(intervalId);
}, []);
请注意,在 JavaScript 中,%
运算符计算余数,而不是 modulus。这两个对于正数是相同的,所以这种方法会起作用,因为你只是递增 imgSource
。如果您希望幻灯片放映改变方向,您必须做更多的工作才能使相同的方法起作用,这里有一个 mod 函数:
export function mod(n, m) {
return ((n % m) + m) % m;
}
你可以这样使用:
setImgSource(prev => mod(prev + 1, 5));