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:
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>