react 中 useEffect 的 setInterval 内状态未正确更新

问题描述 投票:0回答:1

我在更新 setInterval 函数内的

setStartTime
时遇到问题。

我想每分钟更新一次

startTime
。为了更新这一点,我创建了一个
useRef
并将值存储在
timeRef.current
中。每分钟,
startTime
都会更新。

 const [startTimeOffsetMins, setStartTimeOffsetMins] = useState(10)
 const timeRef = useRef(time)
 
  useEffect(() => {
    timeRef.current = time
  }, [moment(time).minutes()]);
 
  useEffect(() => {
    let tempCurrentTime = moment();
    
    const startTimeOffset = activeTab === 0 ? (startTimeOffsetMins + 1) : (startTimeOffsetMins + 10);


    const refreshTimeFunc = () => {
      const nowtime = moment();

      let startTimeInitial = activeTab === 0 ? moment(timeRef.current).add({h: 0, m: 1}).toDate() : moment().toDate();

      if (dynamicStartTime && (moment(tempCurrentTime).minutes() !== moment(nowtime).minutes())) {
        setStartTime(moment(startTimeInitial).add({ h: 0, m: startTimeOffset }).set({ s:0, ms:0}).toISOString());
        tempCurrentTime = moment(nowtime);
      }
    }

    const refreshTimer = setInterval(refreshTimeFunc, 1000);

    return () => {
      clearInterval(refreshTimer);
    }
    
  }, [activeTab, time, dynamicStartTime]);

问题:在 if 条件内,

startTimeInitial
延迟 1 分钟。所以,我添加了
add({h: 0, m: 1})
来补偿。

但考虑一种情况:

dynamicStartTime
是一个具有布尔值的切换按钮。在某些情况下,当
dynamicStartTime
关闭然后打开时,
startTimeInitial

会额外添加 1 分钟

我已阅读答案,说我可以更新

prevState + 1
。但这种情况下,我该如何更新并避免这种情况呢?我正在使用 moment 来更新时间。

reactjs react-hooks setinterval
1个回答
0
投票

取消手动分钟调节。 使用更精确的方法通过比较秒和毫秒来检查是否已经过去了一分钟。 根据

startTimeInitial
activeTab
状态正确更新
dynamicStartTime

这是更新后的代码:

import React, { useEffect, useRef, useState } from 'react';
import moment from 'moment';

const YourComponent = ({ activeTab, dynamicStartTime }) => {
  const [startTime, setStartTime] = useState(moment().toISOString());
  const [startTimeOffsetMins, setStartTimeOffsetMins] = useState(10);
  const timeRef = useRef(moment());
  const entDateTimeRef = useRef(moment()); // Assuming this is defined somewhere in your component

  useEffect(() => {
    timeRef.current = moment();
  }, [moment().minutes()]);

  useEffect(() => {
    let tempCurrentTime = moment();
    
    const startTimeOffset = activeTab === 0 ? (startTimeOffsetMins + 1) : (startTimeOffsetMins + 10);

    const refreshTimeFunc = () => {
      const nowtime = moment();

      let startTimeInitial = activeTab === 0 
        ? moment(entDateTimeRef.current).toDate() 
        : moment().toDate();

      if (dynamicStartTime && (nowtime.diff(tempCurrentTime, 'minutes') >= 1)) {
        setStartTime(moment(startTimeInitial)
          .add({ h: 0, m: startTimeOffset })
          .set({ s: 0, ms: 0 })
          .toISOString());
        tempCurrentTime = moment(nowtime);
      }
    };

    const refreshTimer = setInterval(refreshTimeFunc, 1000);

    return () => {
      clearInterval(refreshTimer);
    };
  }, [activeTab, startTimeOffsetMins, dynamicStartTime]);

  return (
    <div>
      {/* Your component content */}
      Start Time: {startTime}
    </div>
  );
};

export default YourComponent;
© www.soinside.com 2019 - 2024. All rights reserved.