reactjs - 如何使用 React setState 和 setInterval 循环图像轮播?

标签 reactjs setstate

我正在尝试设置一个图像轮播,当您将鼠标悬停在一个 div 上时,它会循环显示 3 个图像。我在尝试弄清楚如何在到达第三张图像后重置循环时遇到问题。我需要重置 setInterval 以便它再次启动并在您将鼠标悬停在 div 上时不断循环显示图像。然后当你鼠标移出 div 时,循环需要停止并重置为初始状态 0。这是代码沙箱:

https://codesandbox.io/s/pedantic-lake-wn3s7

import React, { useState, useEffect } from "react";
import { images } from "./Data";
import "./styles.css";

export default function App() {
  let timer;
  const [count, setCount] = useState(0);

  const updateCount = () => {
    timer = setInterval(() => {
      setCount((prevCount) => prevCount + 1);
    }, 1000);

    if (count === 3) clearInterval(timer);
  };

  const origCount = () => {
    clearInterval(timer);
    setCount((count) => 0);
  };

  return (
    <div className="App">
      <div className="title">Image Rotate</div>
      <div onMouseOver={updateCount} onMouseOut={origCount}>
        <img src={images[count].source} alt={images.name} />
        <p>count is: {count}</p>
      </div>
    </div>
  );
}

最佳答案

任何涉及计时器/间隔的东西都是 useEffect 的绝佳候选者, 因为我们可以很容易地在我们使用 effects with cleanup 设置定时器的地方注册一个清除 Action .这避免了忘记清除间隔的常见陷阱,例如当组件卸载时,或失去对间隔句柄的跟踪时。尝试如下操作:

import React, { useState, useEffect } from "react";
import { images } from "./Data";
import "./styles.css";

export default function App() {
  const [count, setCount] = useState(0);
  const [mousedOver, setMousedOver] = useState(false);

  useEffect(() => {
    // set an interval timer if we are currently moused over
    if (mousedOver) {
      const timer = setInterval(() => {
        // cycle prevCount using mod instead of checking for hard-coded length
        setCount((prevCount) => (prevCount + 1) % images.length);
      }, 1000);
      // automatically clear timer the next time this effect is fired or
      // the component is unmounted
      return () => clearInterval(timer);
    } else {
      // otherwise (not moused over), reset the counter
      setCount(0);
    }
    // the dependency on mousedOver means that this effect is fired
    // every time mousedOver changes
  }, [mousedOver]);

  return (
    <div className="App">
      <div className="title">Image Rotate</div>
      <div
        // just set mousedOver here instead of calling update/origCount
        onMouseOver={() => setMousedOver(true)}
        onMouseOut={() => setMousedOver(false)}
      >
        <img src={images[count].source} alt={images.name} />
        <p>count is: {count}</p>
      </div>
    </div>
  );
}

Edit hungry-einstein-d8pe0

至于为什么您的代码不起作用,有几点:

  1. 你的意思是 if (count === 2) ...,而不是 count === 3。更好的方法是使用 images 数组的长度而不是对其进行硬编码
  2. 此外,count 的值为 stale inside of the closure ,即在您使用 setCount 更新它之后,count 的旧值仍然在 updateCount 中捕获。这实际上是使用功能状态更新的原因,当你说例如setCount((prevCount) => prevCount + 1)
  3. 您需要在间隔内循环计数,而不是在鼠标悬停时清除间隔。如果你仔细考虑它的逻辑,这应该是显而易见的
  4. 一般来说,在 React 中,使用像 timer 这样的函数局部变量不会达到您的预期。总是使用状态和效果,在极少数情况下(不是这个),一些其他的钩子(Hook),比如 refs

关于reactjs - 如何使用 React setState 和 setInterval 循环图像轮播?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69485219/

相关文章:

javascript - 找不到模块 : Can't resolve 'firebase' in

reactjs - React 在子组件中使用箭头函数传递参数

javascript - React.js + Summernote,如何导入JavaScript依赖库

javascript - ReactJs setState 更新与输入框中输入的内容不同步

flutter - Getx Bottomsheet setstate 不更新

reactjs - react redux解析错误: Unexpected character '​'

asp.net - IdentityServer4 无法在生产环境中运行

dictionary - React JS setState({dict : dict })

Flutter setState 函数

javascript - 静态方法中的 setState