【问题标题】:Slideshow using React hooks and setInterval [duplicate]幻灯片使用 React 钩子和 setInterval [重复]
【发布时间】:2021-12-26 05:13:54
【问题描述】:

我正在尝试使用 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 语句不起作用。

【问题讨论】:

    标签: reactjs timer react-hooks setinterval


    【解决方案1】:

    我可以在这里看到两个问题。首先是非常小的:条件应该是imgSource &lt; 4,而不是imgSource &lt;= 1。其次,更重要的是,setImgSource 之外的imgSource 的值被锁定为调用setInterval 时的值(锁定为零)。因此条件始终为真,因为imgSource0,并且该值继续递增超过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 中,% 运算符会做余数,而不是取模。这两个对于正数是相同的,所以这种方法可以工作,因为你只是增加imgSource。如果您希望幻灯片改变方向,您必须做更多的工作才能使相同的方法起作用,这里有一个 mod 函数:

    export function mod(n, m) {
        return ((n % m) + m) % m;
    }
    

    你可以这样使用:

    setImgSource(prev => mod(prev + 1, 5));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-08
      • 2021-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多