フリーランス 技術調査ブログ

フリーランス/エンジニア Ruby Python Nodejs Vuejs React Dockerなどの調査技術調査の備忘録

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

画面

f:id:PX-WING:20200615235418p:plain