20250209 学習記録

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

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

当面の目標：LPIC101,102合格




# React

ストップウォッチコンポーネントの作成
- **ストップウォッチ**
    
    ```tsx
    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 文**
            
            ```tsx
            import { useState, useEffect, useRef } from "react";
            ```
            
            React の **フック (Hook)** を3つインポートしています。
            
            •	useState：コンポーネントの状態 (time と isRunning) を管理
            
            •	useEffect：副作用（ストップウォッチの動作）を設定
            
            •	useRef：setInterval の ID を管理（クリーンアップ用）
            
        - **2. コンポーネントの定義**
            
            ```tsx
            const StopWatch: React.FC = () => {
            ```
            
            この行で **React 関数コンポーネント** を定義しています。
            
            `React.FC`は「このコンポーネントは **Props を受け取らない**」という型指定。
            
        - **3. 状態の定義**
            
            ```tsx
            const [time, setTime] = useState(0);
            ```
            
            •	time：ストップウォッチの **経過時間 (ミリ秒単位)**
            
            •	setTime：time の更新関数
            
            •	初期値は 0（ストップウォッチは 0 秒からスタート）
            
            ```tsx
            const [isRunning, setIsRunning] = useState(false);
            ```
            
            •	isRunning：ストップウォッチの **動作状態 (true:動作中, false:停止中)**
            
            •	setIsRunning：isRunning の更新関数
            
            •	初期値は false（ストップウォッチは停止状態）
            
            ```tsx
            const timerRef = useRef<number | null>(null);
            ```
            
            •	timerRef：setInterval の ID を保持（clearInterval のために使用）
            
            •	初期値は null
            
        - **4. ストップウォッチの動作管理 (useEffect)**
            
            ```tsx
            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 を保存
            
            2.	isRunning が false の場合
            
            •	clearInterval で setInterval を停止
            
            •	timerRef.current を null にリセット
            
            3.	**クリーンアップ処理 (return の関数)**
            
            •	コンポーネントが**アンマウントされる又**は isRunning が変更される時
            
            •	clearInterval を実行し、タイマーを確実に停止
            
        - **5. 時間のフォーマット**
            
            ```tsx
            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
            
            3.	**秒 (seconds) を計算**
            
            •	60000ms 単位の余りを 1000ms で割る
            
            4.	**ミリ秒 (ms) を計算**
            
            •	1000ms の余りを 10ms で割る（00 ～ 99 の範囲に調整）
            
            5.	padStart(2, "0") で **常に2桁表示**
            
            **例**
            
            ```tsx
            	formatTime(75420) // "01:15:42"（1分15秒42ミリ秒）
            ```
            
        - **6. コンポーネントの JSX**
            
            ```tsx
            <>
              <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. スタート / ストップ ボタン**
            
            ```tsx
            <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. リセット ボタン**
            
            ```tsx
            <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. エクスポート**
            
            ```tsx
            export default StopWatch;
            ```
            
            •	export default で **コンポーネントを外部で使用できるようにする**
            
        
        **まとめ**
        
        ✅ useState で **時間と動作状態を管理**
        
        ✅ useEffect で **setInterval の開始・停止を制御**
        
        ✅ useRef で **setInterval の ID を保持し、適切にクリア**
        
        ✅ formatTime() で **時間を「00:00:00」形式に変換**
        
        ✅ button で **スタート / ストップ / リセットを制御**
        
        ✅ Tailwind CSS で **デザインを整える**