简体   繁体   English

Javascript - 如何在 React 中一遍又一遍地循环遍历数组

[英]Javascript - How to loop through an array over and over again in React

Imagine I have an array of objects like this:想象一下,我有一个这样的对象数组:

const items = [
    {name: "item 0"},
    {name: "item 1"},
    {name: "item 2"}
]

And a component like this:像这样的组件:

const [currentItemIndex, setCurrentItemIndex] = useState(0)

setInterval(function () {
   if (currentItemIndex < 3) {
      setCurrentItemIndex(currentItemIndex + 1);
   } else {
      clearInterval();
   }
}, 5000);
   
return (
    <div>
        <p> {items[currentItemIndex].name} <p>
    </div>
)

I want to update currentItemIndex every 5 seconds so the div shows next item, and if it reaches the end, it should start over: 0, 1, 2, 0, 1, 2, 0, 1, 2... .我想每 5 秒更新一次currentItemIndex以便div显示下一个项目,如果它到达末尾,它应该重新开始: 0, 1, 2, 0, 1, 2, 0, 1, 2...

The problem is: it loops correctly the first time, but after reaching the end, it shows the first item for a fraction of a second and then goes to the last item: 0, 1, 2, 0 (really quick to) 2 .问题是:它第一次正确循环,但在到达结尾后,它显示第一个项目的几分之一秒,然后转到最后一个项目: 0, 1, 2, 0 (really quick to) 2

What I'm doing wrong?我做错了什么?
I searched for this, but every article is talking about "how to prevent infinite loops", not "how to use them"!我搜索了这个,但每篇文章都在谈论“如何防止无限循环”,而不是“如何使用它们”!

You can do it with useEffect and with setTimeout like this:您可以使用useEffectsetTimeout来做到这一点,如下所示:

 const items = [{ name: "item 0" }, { name: "item 1" }, { name: "item 2" }]; const App = () => { const [currentItemIndex, setCurrentItemIndex] = React.useState(0); React.useEffect(() => { setTimeout( () => setCurrentItemIndex((currentItemIndex + 1) % items.length), 1000 ); }, [currentItemIndex]); return ( <div> <p> {items[currentItemIndex].name} </p> </div> ); }; // export default App; ReactDOM.render(<App />, document.getElementById('root'));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script> <div id="root"></div>

I see a few problems with this logic that you created.我发现您创建的这种逻辑存在一些问题。

First of all, clearInterval needs to be provided a variable that you created when creating the setInterval function (as you can see here ), so this clearInterval() is doing nothing.首先,需要为clearInterval提供一个您在创建setInterval function 时创建的变量(如您在此处看到的),所以这个clearInterval()什么都不做。

Besides that, you do not want to clear your timer when currentItemIndex reaches its threshold, but instead you want it to go back to zero.除此之外,您不想在currentItemIndex达到其阈值时清除计时器,而是希望它 go 回到零。

In React, we usually use useEffect for timing events as you need to clear them on unmount so you don't keep them running after your component is unmounted.在 React 中,我们通常使用useEffect来计时事件,因为您需要在卸载时清除它们,这样您就不会在组件卸载后继续运行它们。 Something like this:像这样的东西:

useEffect(() => {
    const timer = setInterval(yourFunction);
    return () => clearInterval(timer);
}, [])

You can use this approach if you want to.如果您愿意,可以使用这种方法。 You create a function using which will set state after 5 seconds using timeout.您创建一个 function 使用它将在 5 秒后使用超时设置 state。 Once the state is set you again call the same method.设置 state 后,您再次调用相同的方法。 For sake of react you call this method once using useEffect.为了做出反应,您使用 useEffect 调用此方法一次。

import { useEffect, useState } from "react";


const items = [{ name: "item 0" }, { name: "item 1" }, { name: "item 2" }];


export default function App() {
  const [currentItemIndex, setCurrentItemIndex] = useState(0);

  useEffect(() => {
    incrementAfterDelay(1000, 1, 2);
  }, []);

  const incrementAfterDelay = (delay, step, lastStep) => {
    setTimeout(
      () =>
        setCurrentItemIndex((value) => {
          return (value < lastStep)? value + step : 0
        }, incrementAfterDelay(delay, step, lastStep)),
      delay
    );
  };

  return (
    <div>
      <p> {items[currentItemIndex].name} </p>
    </div>
  );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM