0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

20250209 学習記録

Posted at

現状:

エンジニアへの未経験転職。
就職先も決まり、2月からひよこエンジニアに。

内容は常に書き散らしのメモです、あしからず。

当面の目標:LPIC101,102合格

React

ストップウォッチコンポーネントの作成

  • ストップウォッチ

    import { useState, useEffect, useRef } from "react";
    
    const StopWatch: React.FC = () => {
      const [time, setTime] = useState(0);
      const [isRunning, setIsRunning] = useState(false);
      const timerRef = useRef<number | null>(null);
    
      useEffect(() => {
        if (isRunning) {
          timerRef.current = window.setInterval(() => {
            setTime((prevTime) => prevTime + 10);
          }, 10);
        } else {
          if (timerRef.current !== null) {
            clearInterval(timerRef.current);
            timerRef.current = null;
          }
        }
        return () => {
          if (timerRef.current !== null) {
            clearInterval(timerRef.current);
            timerRef.current = null;
          }
        };
      }, [isRunning]);
    
      const formatTime = (milliseconds: number) => {
        const minutes = Math.floor(milliseconds / 60000);
        const seconds = Math.floor((milliseconds % 60000) / 1000);
        const ms = Math.floor((milliseconds % 1000) / 10);
    
        return `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(
          2,
          "0"
        )}:${String(ms).padStart(2, "0")}`;
      };
    
      return (
        <>
          <div className="p-4 max-w-sm mx-auto border rounded-lg shadow-md text-center">
            <h2 className="text-xl font-semibold mb-2">StopWatch</h2>
            <div className="text-3xl font-mono p-4 border rounded bg-gray-100">
              {formatTime(time)}
            </div>
            <div className="mt-4 space-x-2">
              <button
                className={`px-4 py-3 text-white rounded ${
                  isRunning
                    ? "bg-red-500 hover:bg-red-600"
                    : "bg-green-500 hover:bg-green-600"
                }`}
                onClick={() => setIsRunning(!isRunning)}
              >
                {isRunning ? "Stop" : "Start"}
              </button>
              <button
                className="px-4 py-2 bg-gray-500 text-white rounded hober:bg-gray-600"
                onClick={() => {
                  setTime(0);
                }}
              >
                reset
              </button>
            </div>
          </div>
        </>
      );
    };
    
    export default StopWatch;
    
    
    • 解説(ChatGPT)

      コードの詳細解説:StopWatch コンポーネント

      • 1. import 文

        import { useState, useEffect, useRef } from "react";
        

        React の フック (Hook) を3つインポートしています。

        • useState:コンポーネントの状態 (time と isRunning) を管理

        • useEffect:副作用(ストップウォッチの動作)を設定

        • useRef:setInterval の ID を管理(クリーンアップ用)

      • 2. コンポーネントの定義

        const StopWatch: React.FC = () => {
        

        この行で React 関数コンポーネント を定義しています。

        React.FCは「このコンポーネントは Props を受け取らない」という型指定。

      • 3. 状態の定義

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

        • time:ストップウォッチの 経過時間 (ミリ秒単位)

        • setTime:time の更新関数

        • 初期値は 0(ストップウォッチは 0 秒からスタート)

        const [isRunning, setIsRunning] = useState(false);
        

        • isRunning:ストップウォッチの 動作状態 (true:動作中, false:停止中)

        • setIsRunning:isRunning の更新関数

        • 初期値は false(ストップウォッチは停止状態)

        const timerRef = useRef<number | null>(null);
        

        • timerRef:setInterval の ID を保持(clearInterval のために使用)

        • 初期値は null

      • 4. ストップウォッチの動作管理 (useEffect)

        useEffect(() => {
          if (isRunning) {
            timerRef.current = window.setInterval(() => {
              setTime((prevTime) => prevTime + 10);
            }, 10);
          } else {
            if (timerRef.current !== null) {
              clearInterval(timerRef.current);
              timerRef.current = null;
            }
          }
          return () => {
            if (timerRef.current !== null) {
              clearInterval(timerRef.current);
              timerRef.current = null;
            }
          };
        }, [isRunning]);
        

        動作の流れ

        1. isRunning が true の場合

        • setInterval を 10ms ごとに実行

        • setTime で time を 10ms ずつ増加

        • timerRef.current に setInterval の ID を保存

        1. isRunning が false の場合

        • clearInterval で setInterval を停止

        • timerRef.current を null にリセット

        1. クリーンアップ処理 (return の関数)

        • コンポーネントがアンマウントされる又は isRunning が変更される時

        • clearInterval を実行し、タイマーを確実に停止

      • 5. 時間のフォーマット

        const formatTime = (milliseconds: number) => {
          const minutes = Math.floor(milliseconds / 60000);
          const seconds = Math.floor((milliseconds % 60000) / 1000);
          const ms = Math.floor((milliseconds % 1000) / 10);
        
          return `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(
            2,
            "0"
          )}:${String(ms).padStart(2, "0")}`;
        };
        

        動作の流れ

        1. milliseconds(ミリ秒単位の数値)を受け取る

        2. 分 (minutes) を計算

        • 60000ms = 1分 なので milliseconds / 60000

        1. 秒 (seconds) を計算

        • 60000ms 単位の余りを 1000ms で割る

        1. ミリ秒 (ms) を計算

        • 1000ms の余りを 10ms で割る(00 ~ 99 の範囲に調整)

        1. padStart(2, "0") で 常に2桁表示

        	formatTime(75420) // "01:15:42"(1分15秒42ミリ秒)
        
      • 6. コンポーネントの JSX

        <>
          <div className="p-4 max-w-sm mx-auto border rounded-lg shadow-md text-center">
            <h2 className="text-xl font-semibold mb-2">StopWatch</h2>
            <div className="text-3xl font-mono p-4 border rounded bg-gray-100">
              {formatTime(time)}
            </div>
            <div className="mt-4 space-x-2">
        

        • div で コンポーネント全体を囲む

        • h2 で タイトル「StopWatch」

        • div で ストップウォッチの時間を表示

        • formatTime(time) を適用し、00:00:00 の形式 で表示

        • Tailwind CSS を使用し、デザインを整える

      • 7. スタート / ストップ ボタン

        <button
          className={`px-4 py-3 text-white rounded ${
            isRunning
              ? "bg-red-500 hover:bg-red-600"
              : "bg-green-500 hover:bg-green-600"
          }`}
          onClick={() => setIsRunning(!isRunning)}
        >
          {isRunning ? "Stop" : "Start"}
        </button>
        

        • isRunning が true なら 「Stop」ボタン

        • false なら 「Start」ボタン

        • onClick={() => setIsRunning(!isRunning)} で ボタンのクリック時に状態を切り替え

        • bg-red-500 / bg-green-500 で 状態に応じて色を変化

      • 8. リセット ボタン

        <button
          className="px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600"
          onClick={() => {
            setIsRunning(false);
            setTime(0);
          }}
        >
          reset
        </button>
        

        • onClick 時に ストップウォッチを停止 (isRunning = false)

        • setTime(0) で 時間を 0 にリセット

        • bg-gray-500 で デザインを調整

      • 9. エクスポート

        export default StopWatch;
        

        • export default で コンポーネントを外部で使用できるようにする

      まとめ

      ✅ useState で 時間と動作状態を管理

      ✅ useEffect で setInterval の開始・停止を制御

      ✅ useRef で setInterval の ID を保持し、適切にクリア

      ✅ formatTime() で 時間を「00:00:00」形式に変換

      ✅ button で スタート / ストップ / リセットを制御

      ✅ Tailwind CSS で デザインを整える

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?