Home > front end >  add a time offset to a date object and passing it as a prop
add a time offset to a date object and passing it as a prop

Time:12-30

I have an assignment in which i have to display 10 analog clocks, only with a second hand. every clock shows the time one second forward in comparing to the one above. they should all be in the same component.

i was thinking about using the delay as a prop for each component and wrapping them with another component.

this is the code i wrote so far:


 interface IProps {
    offset: {
        offsetValue: number 
    }
}
 
const Clock = (props: IProps) => {
    
    
    
const [time,setTime] = useState(new Date())

useEffect(() => {
    
    const interval = setInterval( () => setTime(new Date))
    //props.offset
})
    
    
    let sec = time.getSeconds()
    
    
    
    
    
    
    
    
    return (
        <div>
            
        </div>
    )
}

export default Clock

I'm completely lost

CodePudding user response:

Simply add this offset number to the Date displayed, as seconds.

const Clock = (props: IProps) => {
    const { offset: { offsetValue } } = props;
    const interval = useRef<number|null>(null);
    const [time, setTime] = useState<Date|null>(null);

    useEffect(() => {
        interval.current = setInterval(() => {
            const now = new Date();
            const withOffset = new Date(now.getTime()   offsetValue*1000);
            setTime(withOffset);
        }, 1000);
    }, []);

    return (
        <span>{time}</span>
    );
}

CodePudding user response:

You should initialize your state with a date that includes the offset from props. Also, be sure to return a cleanup function from your effect hook callback so that the interval stops when the component unmounts. Otherwise, it'll create a leak where the interval timer keeps going after your component no longer exists (and try to update the state which no longer exists, etc.). I've provided a commented example below:

TS Playground

import {default as React, ReactElement, useEffect, useState} from 'react';

const SECOND = 1000; // 1s in ms

// get a new date from the current unix time (in ms), offset by a value (in seconds)
function getOffsetDate (seconds: number): Date {
  return new Date(Date.now()   (SECOND * seconds));
}

type ClockProps = {
  offset: {
    offsetValue: number; // seconds
  };
};
 
const Clock = (props: ClockProps): ReactElement => {
  const {offset: {offsetValue}} = props;
  // initialize state with the offset date
  const [date, setDate] = useState(getOffsetDate(offsetValue));

  useEffect(() => {
    // start an interval timeer, assign the timer ID to a variable
    const timerId = setInterval(() => {
      // create a new offset date
      const d = getOffsetDate(offsetValue);
      setDate(d);
    }, SECOND); // repeat the interval each second

    // return cleanup function from effect hook:
    // clear the interval timer using its ID so it stops when your component unmounts
    return () => clearInterval(timerId);
  // not strictly necessary, but exhaustive to add setDate to the dependency list
  }, [setDate]);

  return (
    <span>{date.getSeconds()}</span>
  );
};

You can see it working here:

<div id="root"></div><script src="https://unpkg.com/[email protected]/umd/react.development.js"></script><script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script><script src="https://unpkg.com/@babel/[email protected]/babel.min.js"></script><script>Babel.registerPreset('tsx', {presets: [[Babel.availablePresets['typescript'], {allExtensions: true, isTSX: true}]]});</script>
<script type="text/babel" data-type="module" data-presets="tsx,react">

const {useEffect, useState} = React;

const SECOND = 1000; // 1s in ms

// get a new date from the current unix time (in ms), offset by a value (in seconds)
function getOffsetDate (seconds: number): Date {
  return new Date(Date.now()   (SECOND * seconds));
}

type ClockProps = {
  offset: {
    offsetValue: number; // seconds
  };
};
 
const Clock = (props: ClockProps): ReactElement => {
  const {offset: {offsetValue}} = props;
  // initialize state with the offset date
  const [date, setDate] = useState(getOffsetDate(offsetValue));

  useEffect(() => {
    // start an interval timeer, assign the timer ID to a variable
    const timerId = setInterval(() => {
      // create a new offset date
      const d = getOffsetDate(offsetValue);
      setDate(d);
    }, SECOND); // repeat the interval each second

    // return cleanup function from effect hook:
    // clear the interval timer using its ID so it stops when your component unmounts
    return () => clearInterval(timerId);
  // not strictly necessary, but exhaustive to add setDate to the dependency list
  }, [setDate]);

  return (
    <span>{date.getSeconds()}</span>
  );
};

function Example () {
  const [offsets, setOffsets] = useState([...new Array(5).keys()]);
  return (
    <div>
      {
        offsets.map(seconds => (
          <div key={seconds}>
            {seconds < 0 ? '-' : ' '}{Math.abs(seconds)}: <Clock offset={{offsetValue: seconds}} />
          </div>
        ))
      }
    </div>
  );
}

ReactDOM.render(<Example />, document.getElementById('root'));

</script>

  • Related