現在の時刻を表示し続けるもの(デジタル時計)をつくる

React.jsで現在の時刻を表示するデジタル時計を作ってみましょう。

普通にJavaScriptの感覚で作成すると、ハマってしまうようである。

 

[React] 現在の日付と時刻を表示する(デジタル時計) | FEELD BLOG (feeld-uni.com)

これによると、useStateとuseEffectを使う必要があるようである。

www.youtube.com

 

useEffectを使わず、useStateだけで書けないかどうか考えてみます。

まずは静的なページの作成からです。

RealTimeClock.js

const RealtimeClock = ()=>{
  const dateTime = new Date();
  const time = dateTime.getHours() + ":"
               + dateTime.getMinutes() + ":"
               + dateTime.getSeconds();
 
  return(
      <div>
        <p>{time}</p>
      </div>
  )
}

export default RealtimeClock;

次はボタンを押すと時刻が変わるようにします。

import {useState} from 'react';

const RealtimeClock = ()=>{
  const dateTime = new Date();
  const startTime = dateTime.getHours() + ":"
                    + dateTime.getMinutes() + ":"
                    + dateTime.getMilliseconds();
  const [time,setTime] = useState(startTime);

  const changeTime = ()=>{
    const nextTime = dateTime.getHours() + ":"
                      + dateTime.getMinutes() + ":"
                      + dateTime.getSeconds();
    setTime(nextTime);
  }

  return(
      <div>
        <p>{time}</p>
        <button type="button" onClick={changeTime}>PUSH</button>
      </div>
  )
}

export default RealtimeClock;

 

最後は、stateが変更されれば(ここではsetTimeoutで1秒ごとにstateを変える記述を追記してます)、自動的にレンダリングされることを念頭におきながら記載すると、完成です。

import {useState} from 'react';

const RealtimeClock = ()=>{

  const [time,setTime] = useState('');

  const changeTime = ()=>{
    const dateTime = new Date();
    const nextTime = dateTime.getHours() + ":"
                      + dateTime.getMinutes() + ":"
                      + dateTime.getSeconds();
    setTime(nextTime);
  }

  setTimeout(changeTime,1000);

  return(
      <div>
        <p value ={time}
           onChange={changeTime}>{time}</p>
      </div>
  )
}

export default RealtimeClock;

 

いくつか気づいた点があります。

stateの初期値と変更する値が同じなら、1回しかレンダリング(マウント)されないので、時間は初めの時刻表示でとまってしまう。

 

techplay.jp

 

見やすくし、不要なものを削除しました。

import {useState} from 'react';

const RealtimeClock = ()=>{

  const [time,setTime] = useState('');

  const dateTime = new Date();
  const nextTime = dateTime.getHours() + ":"
                    + dateTime.getMinutes() + ":"
                    + dateTime.getSeconds();

  const changeTime = ()=>{
    setTime(nextTime);
  }

  setTimeout(changeTime,1000);

  return(
      <div>
        <p>{time}</p>
      </div>
  )
}

export default RealtimeClock;