ReactHooksでカウンターダウンコンポーネントを作成する
はじめに
- 会員登録機能でユーザーに誕生日を登録して持ったので、誕生日までのカウントダウンコンポーネントを作成しようと思いましたが、 指定の時間を入力して、入力した時間のカウントダウンのコンポーネントを作成することにしました。
- 時間の操作はmomentを利用して簡易的に行う
- スタートボタンがクリックされたときに「開始」とメッセージを通知し、タイムオーバー時に「終了」というメッセージを通知する処理にしてみました。
コード
もっと効率的な書き方で書き直したい。
import React, { useEffect, useState } from 'react'
import moment from 'moment'
const CountDownTimer = () => {
const [timeLeft, setTimeLeft] = useState({});
const [timeNow, setTimeNow] = useState(0);
const [timeHour, setTimeHour] = useState(0);
const [timeMin, setTimeMin] = useState(0);
const [timeSec, setTimeSec] = useState(0);
const timerComponents = [];
const calculateTimeLeft = () => {
let timeLeft = {};
if ((timeHour > 0) || (timeMin > 0) || (timeSec > 0)) {
const difference = timeNow - moment().unix()
console.log(difference)
if (difference > -1) {
timeLeft = {
'日': Math.floor(difference / (60 * 60 * 24)),
'時間': Math.floor((difference / (60 * 60)) % 24),
'分': Math.floor((difference / 60) % 60),
'秒': Math.floor((difference) % 60)
};
}
if (difference == 0) {
const endAnnounce = new SpeechSynthesisUtterance("終了")
speechSynthesis.speak(endAnnounce)
}
}
return timeLeft;
};
useEffect(
() => {
if (timeNow > 0 ){
let timer1 = setTimeout(() => {
const result = calculateTimeLeft()
if (Object.keys(result).length > 0){
setTimeLeft(result)
}
}, 1000)
return () => {
clearTimeout(timer1)
}
}
}
)
Object.keys(timeLeft).forEach(interval => {
if (!timeLeft[interval]) {
return;
}
timerComponents.push(
<span>
{timeLeft[interval]} {interval}{" "}
</span>
);
});
const endTime = () => {
return (<span>時間が来ました。</span>)
}
const startTime = (e) => {
const startAnnounce = new SpeechSynthesisUtterance("開始")
speechSynthesis.speak(startAnnounce)
setTimeNow(moment().add(timeHour, 'hours').add(timeMin, 'minutes').add((Number(timeSec)+1), 'seconds').unix())
}
return (
<div>
<input name="min" type="number" value={timeHour} onChange={(e) => { setTimeHour(e.target.value) }} />時
<input name="min" type="number" value={timeMin} onChange={(e) => { setTimeMin(e.target.value) }} />分
<input name="sec" type="number" value={timeSec} onChange={(e) => { setTimeSec(e.target.value) }} />秒<br />
<input type="button" value="スタート" onClick={startTime}/>
{timerComponents.length ? timerComponents : endTime()}
</div>
);
}
export default CountDownTimer
画面
