skip to Main Content

I’m facing issue in updating the setStartTime inside setInterval function.

I want to update the startTime every minute. To update that, I’ve created a useRef and storing the value in timeRef.current. Every minute, startTime is getting updated.

 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]);

Issue: Inside the if condition, startTimeInitial is getting 1 min delay. So, I added add({h: 0, m: 1}) to compensate.

But considering one scenario: dynamicStartTime is a toggle button which has boolean. In some scenario when dynamicStartTime is toggled OFF then ON, an extra 1 minute is added to startTimeInitial

I have read answers which says I can update prevState + 1. But in this case, how can I update and avoid this situation. I am using moment to update time.

2

Answers


  1. Chosen as BEST ANSWER

    The tempCurrentTime and nowTime should check the time variable to see any update. When the time value changes every minutes, we can compare old and new minutes. Also, we can remove the (startTimeOffsetMins + 1)

    Modified code:

    useEffect(() => {
       timeRef.current = time
     }, [moment(time).minutes()]);
    
     useEffect(() => {
       let tempCurrentTime = moment(time).toDate();
       
       const startTimeOffset = activeTab === 0 ? startTimeOffsetMins : (startTimeOffsetMins + 10);
    
    
       const refreshTimeFunc = () => {
         const nowtime = moment(time).toDate();
    
         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).toDate();
         }
       }
    
       const refreshTimer = setInterval(refreshTimeFunc, 1000);
    
       return () => {
         clearInterval(refreshTimer);
       }
       
     }, [activeTab, time, dynamicStartTime]);
    

  2. Remove the manual minute adjustment.
    Use a more precise way to check if a minute has passed by comparing seconds and milliseconds.
    Update startTimeInitial correctly based on the activeTab and dynamicStartTime state.

    Here’s the updated code:

    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;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search