【React】ストップウォッチを作ってみる
プロジェクト作成
npx create-react-app timer-app
完成コード
import React, { useState, useRef } from 'react';
function Stopwatch() {
const [time, setTime] = useState(0);
const [isRunning, setIsRunning] = useState(false);
const intervalRef = useRef(null);
function handleStart() {
setIsRunning(true);
intervalRef.current = setInterval(() => {
setTime(prevTime => prevTime + 10);
}, 10);
}
function handlePause() {
clearInterval(intervalRef.current);
setIsRunning(false);
}
function handleReset() {
clearInterval(intervalRef.current);
setIsRunning(false);
setTime(0);
}
const milliseconds = `0${(time % 1000) / 10}`.slice(-2);
const seconds = `0${Math.floor(time / 1000) % 60}`.slice(-2);
const minutes = `0${Math.floor(time / 60000) % 60}`.slice(-2);
const hours = `0${Math.floor(time / 3600000)}`.slice(-2);
return (
<div>
<h1>Stopwatch</h1>
<p>{hours}:{minutes}:{seconds}:{milliseconds}</p>
{isRunning ? (
<button onClick={handlePause}>Pause</button>
) : (
<button onClick={handleStart}>Start</button>
)}
<button onClick={handleReset}>Reset</button>
</div>
);
}
export default Stopwatch;
解説
import React, { useState, useRef } from 'react';
このコードは、Reactでコンポーネントを作成する際によく使用されるパターンです。
import文を使用して、ReactとuseStateとuseRefという2つのフックをインポートしています。
ReactはReactライブラリを使用するために必要なものであり、
useStateフックはコンポーネント内で状態を管理するために使用されます。
useRefフックは、コンポーネントのレンダリング中に値を保存するために使用されます。
この例では、ストップウォッチのinterval IDを保存するために使用されています。
function Stopwatch() {
const [time, setTime] = useState(0);
const [isRunning, setIsRunning] = useState(false);
const intervalRef = useRef(null);
このコードは、Reactの関数コンポーネントであるStopwatchを定義しています。
useStateフックを使用して、timeとisRunningという2つの状態を管理しています。
timeはストップウォッチの経過時間を表し、isRunningはストップウォッチが実行中かどうかを表します。useStateフックは、現在の状態とその状態を更新するための関数を返します。
useRefフックを使用して、intervalRefという新しい変数を定義しています。
intervalRefは、setInterval関数で使用されるinterval IDを保存するために使用されます。useRefフックは、レンダリングの間に値を保存するために使用されます。ここでは、intervalRefをnullで初期化しています。
function handleStart() {
setIsRunning(true);
intervalRef.current = setInterval(() => {
setTime(prevTime => prevTime + 10);
}, 10);
}
このコードは、handleStartという関数を定義しています。
この関数は、ストップウォッチを開始するために使用されます。
まず、setIsRunningを使用してisRunning状態をtrueに設定します。
次に、setIntervalを使用して、ストップウォッチを更新するためのインターバルを設定します。setIntervalは、指定された間隔で関数を繰り返し呼び出します。ここでは、10ミリ秒ごとに、setTimeを使用してtime状態を更新します。
setTimeには、現在のtime値に10を加算した値を渡しています。
setTimeには、前のtime値が引数として渡されます。
これは、Reactが状態を更新するときに前の値を保持するために使用されるパターンです。
function handlePause() {
clearInterval(intervalRef.current);
setIsRunning(false);
}
このコードは、handlePauseという関数を定義しています。
この関数は、ストップウォッチを一時停止するために使用されます。
まず、clearIntervalを使用して、setIntervalで設定されたインターバルをクリアします。intervalRef.currentには、現在のinterval IDが保存されています。
次に、setIsRunningを使用して、isRunning状態をfalseに設定します。
これにより、ストップウォッチが実行中でないことが示されます。
function handleReset() {
clearInterval(intervalRef.current);
setIsRunning(false);
setTime(0);
}
このコードは、handleResetという関数を定義しています。
この関数は、ストップウォッチをリセットするために使用されます。
まず、clearIntervalを使用して、setIntervalで設定されたインターバルをクリアします。
次に、setIsRunningを使用して、isRunning状態をfalseに設定します。
これにより、ストップウォッチが実行中でないことが示されます。
最後に、setTimeを使用して、time状態を0に設定します。
これにより、ストップウォッチの経過時間がリセットされます。
const milliseconds = `0${(time % 1000) / 10}`.slice(-2);
const seconds = `0${Math.floor(time / 1000) % 60}`.slice(-2);
const minutes = `0${Math.floor(time / 60000) % 60}`.slice(-2);
const hours = `0${Math.floor(time / 3600000)}`.slice(-2);
このコードは、現在のストップウォッチの時間(time状態)を、ミリ秒、秒、分、時間の単位に分割します。
まず、time状態を1000で割った余りを計算して、ミリ秒を取得します。その後、0${}の形式で文字列を作成し、slice(-2)で2桁に整形します。
次に、time状態を1000で割り、floor関数を使用して、秒数を取得します。60で割った余りを計算して、秒数を60未満の数値に整形します。
同様に、time状態を60000で割り、floor関数を使用して、分数を取得します。60で割った余りを計算して、分数を60未満の数値に整形します。
最後に、time状態を3600000で割り、floor関数を使用して、時間を取得します。0${}の形式で文字列を作成し、slice(-2)で2桁に整形します。
return (
<div>
<h1>Stopwatch</h1>
<p>{hours}:{minutes}:{seconds}:{milliseconds}</p>
{isRunning ? (
<button onClick={handlePause}>Pause</button>
) : (
<button onClick={handleStart}>Start</button>
)}
<button onClick={handleReset}>Reset</button>
</div>
);
}
このコードは、ストップウォッチのUIをレンダリングするためのreturn文を含んでいます。
最初の行では、<h1>
タグを使用して、「Stopwatch」という見出しを表示しています。
次の行では、計測中のストップウォッチの時間を表示しています。
これは、先に定義した時間単位の文字列を含んだ文字列を使用して、<p>
タグで
レンダリングされます。
その後、isRunning状態に応じて、開始/一時停止ボタンが表示されます。
isRunningがtrueの場合、handlePause関数を呼び出す「Pause」ボタンが表示されます。
それ以外の場合、handleStart関数を呼び出す「Start」ボタンが表示されます。
最後に、「Reset」ボタンが表示されます。このボタンがクリックされた場合、handleReset関数が呼び出され、ストップウォッチがリセットされます。
export default Stopwatch;
このコードは、Stopwatchコンポーネントを他のファイルからインポートできるようにするためのエクスポート文です。
export default Stopwatchという文言は、Stopwatchコンポーネントをデフォルトでエクスポートすることを示しています。これにより、他のファイルでStopwatchコンポーネントをインポートする際に、import Stopwatch from './Stopwatch'
のように簡単にインポートすることができます。
Discussion