reactjs 如何为数组中的每个项目创建倒计时器?

8zzbczxx  于 2023-02-18  发布在  React
关注(0)|答案(1)|浏览(109)

在我的React应用程序中,我有一个订单列表,应该只向用户显示30秒,所以每个订单的持续时间属性值为30秒:

[
  {
    ...,
    ...,
    duration: 30
  },
  {
    ...,
    ...,
    duration: 30
  },
  ...
]

我使用Redux Toolkit来存储它们的数据,这样我就可以在不同的组件中呈现这些项目的UI。我尝试创建一个每1秒调度一次的操作,以将持续时间减少1:

decrementCountdown: (state, action) => {
  const order = state.entities[action.payload];
  
  if (order) order.duration -= 1;
}

然后,在App.jsx中,我在一个循环中使用setInterval分派该操作:

useEffect(() => {
  let countdown;

  for (order of orders) {
    // Run until the duration reaches zero
    if (order.duration > 1) {
      countdown = setInterval(() => dispatch(decrementCountdown(order?.id)), 1000);
    }
  }

return () => clearInterval(countdown);
}, [orders])

具有挑战性的部分是计时器必须同步,以便在显示项目的任何地方,显示相同的剩余时间并递减。
我所使用的方法没有多大帮助,特别是当存在多个订单时,在这种情况下,新订单的持续时间不会减少,这会导致useEffect内部的无限循环。
有没有什么办法可以为每一个创建倒计时?

zqry0prt

zqry0prt1#

你真的需要保存倒计时吗?这是个坏主意,因为每一秒你都会触发使用这个数据的组件的重新渲染。
也许你可以创建一个倒计时组件?

function CountDown(props) {
   const [counter, setCounter] = useState(+props.duration);
   useEffect(() => {
       const interval = setInterval(() => {
           setCounter(counter - 1);
           if (counter <= 0) {
              clearInterval(interval);
              props.onEnd?.(); // here u can pass any actions after countDown is ended
           }
       }), 1000);

       return () => clearInterval(interval);
   }, []);
   return <div>{props.counter}</div>
}

但是如果你需要在redux中保存倒计时,我建议你把它从订单对象中移到数组中,在这个数组中你可以保存每个订单的计数器和间隔。

相关问题