【问题标题】:Loop through a new json object every X seconds每 X 秒循环一个新的 json 对象
【发布时间】:2020-10-12 14:45:19
【问题描述】:

我正在尝试设置计时器或间隔。这样每 X 秒就会在屏幕上显示一个新数据。我目前有一组对象,我想同时显示一个对象,并且每 X 秒刷新一次数据。

这是我的 json:

{
    "exampleData": [
        {
            "id": 1,
            "title": "fun film",
            "genre": "comedy"
        },
        {
            "id": 2,
            "title": "not so fun film",
            "genre": "horror"
        }
    ]
}

这是我的小地图功能:

 const renderExample= data.exampleData.map(function (data, idx) {
      return (
         <h2 key={idx}>
            {data.title}
            {data.genre}
         </h2>
      )
   });

因此,当渲染组件时,我希望显示第一个对象:标题:有趣的电影和流派喜剧然后在 X 秒后我希望显示另一个对象不是这样有趣的电影,类型恐怖

我正在考虑将 useEffect 与 setTimout 一起使用,但我不太确定从哪里开始。有什么建议吗?

【问题讨论】:

  • 考虑从尝试实现您最初的想法开始?
  • 你的做法是合理的。提示:使用useState 存储元素的当前索引。您可以使用数组的长度和模运算符定期更新useEffect 中的状态。你应该先自己尝试。
  • @trixn 是的,如果可能的话。我正在努力使用useEffect。我创建了一个 [index, setIndex] 状态并计算数组的长度。但是,我仍然一次渲染所有项目。
  • 也许可以阅读this tutorial,然后让我们知道您是否仍然遇到问题。实际上,当我在网上搜索时,我发现到处都是很棒的教程,所以你真的卡在哪里了? “不太确定从哪里开始”真的很模糊。尝试将其提炼为更具体的问题。

标签: javascript reactjs use-effect


【解决方案1】:

您可以每 X 秒增加一次索引并使用 modulo operator 保持它循环。 (以下未经测试的示例。)

const Your_Component = () => {
  const [current, setCurrent] = useState(0);
  const [data, setData] = useState(null);

  useEffect(() => {
    const intervalID = setInterval(() => {
      setCurrent((current) => (current + 1) % data.length);
    }, 5000) // 5 seconds

    return () => clearInterval(intervalID);
  }, []);

  return (
    <h2>
      {data[current].title}
      {data[current].genre}
    </h2>
  )
}

【讨论】:

  • 由于setIntervalcurrent 的关闭,您的代码只会将current 从0 更改为1,因为您省略了useEffect 挂钩的依赖关系。添加依赖项 (useEffect(() =&gt; {...}, [current, data.length]);) 将解决问题,但随后 useEffect 将不必要地执行多次。您可以在组件外部声明current。这样useEffect 将不依赖于current,它只会执行一次。
  • @Yousaf 我明白你的意思,很好的提示。如果我理解这一点,这可以通过将函数传递给setCurrent 而不是新索引来轻松解决。查看已编辑的 sn-p
  • 是的,更新后的代码将起作用。尽管在这种情况下并不重要,但您仍然从依赖数组中省略了data.length
【解决方案2】:

我会这样做。与其他人相同的一般概念,并带有一个工作示例。

主要区别在于它使用了setActive 的函数形式,它可以防止闭包在这种情况下成为问题。

const { useState, useEffect } = React;
const data = {
  exampleData: [
    {
      id: 1,
      title: 'fun film',
      genre: 'comedy',
    },
    {
      id: 2,
      title: 'not so fun film',
      genre: 'horror',
    },
  ],
};
function Example() {
  const [active, setActive] = useState(0);
  useEffect(() => {
    // create an interval
    const intervalId = setInterval(() => {
      // increment and modulo the active state so it never goes out of bounds.
      // Set the new active using the function form of setActive so the closure doesn't matter
      setActive((active) => (active + 1) % data.exampleData.length);
    }, 1000);
    // Clean up the effect
    return () => clearInterval(intervalId);
  }, []);
  const currentData = data.exampleData[active];

  return (
    <h2>
      {currentData.title}
      {currentData.genre}
    </h2>
  );
}

ReactDOM.render(<Example />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root"/>

【讨论】:

    猜你喜欢
    • 2015-06-29
    • 2018-09-29
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    • 2011-01-14
    • 1970-01-01
    • 2016-07-15
    • 1970-01-01
    相关资源
    最近更新 更多