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?

Next.js × TypeScript 100本ノック Day4 — 「ポモドーロ・タイマー(作業↔休憩サイクル+通知)」

Last updated at Posted at 2025-08-17

1. はじめに

「Next.js × TypeScript 100本ノック」企画の4日目。この企画は、1日1アプリMVP完成を目標に、毎日異なる題材をもとにNext.js × TypeScriptで実装を行い、その過程で新しい技術やパターンを学んでいく100本ノック企画です。

前回の記事はこちら

本日はポモドーロ・タイマーを作りました。
Day3(ToDo Lite)では「状態をReactで扱う」「シンプルに保存する」の基本を練習。Day4は時間を扱うUI(タイマー)に踏み込み、useEffect×setIntervalの安全な使い方、通知(Web Notifications)、そしてSSR/CSRの違いによるハマりを実体験で学びます。

今回のDay4の位置づけ

  • useEffect のクリーンアップでタイマーを安全に制御
  • 作業↔休憩サイクルロングブレイクの状態遷移設計
  • 通知(権限取得/発火)とタブタイトル更新
  • 短い効果音(Web Audio) の最小実装

成果物一覧: https://knock-five.vercel.app/knocks


2. Day4の課題と目的

課題:

  • 25分作業→5分休憩のポモドーロ・タイマー
  • 開始 / 一時停止 / リセット / スキップ
  • フェーズ切替で通知(任意)&サウンド(任意)
  • 指定回数ごとにロングブレイク(例:4回ごと)

学習目的:

  • useEffectsetInterval副作用+クリーンアップパターン
  • 関数型アップデートsetState(prev => ...))で安全に残り時間を更新
  • SSR安全なブラウザAPIの扱い(window / document / Notification
  • 状態遷移の設計(phase: work/break + isLong + rounds管理)

3. 完成イメージ

day4_output


4. 使用技術と依存ライブラリ

  • Next.js (App Router) + React + TypeScript
  • Tailwind CSS
  • Web Notifications API(任意)
  • Web Audio API(任意)

5. 実装コード全文

ソースコード全文はGitHubにあります:
matcha4smiley/knock


6. ハマりポイントと解決策

  • Hydration failed(SSRとCSRで表示がズレる)
    → 初回は必ず同じマークアップを出す(mountedフラグで「判定中…」を表示)。Notification.permission 等のブラウザAPIは**useEffect後にstateへ反映**して分岐。
  • タイマーの二重起動/リーク
    useEffectsetInterval を張り、必ずクリーンアップで clearInterval
  • 0秒チラつき & autoNextが効かない
    → フェーズ切替時に0を返さず次フェーズの秒数を返す。
  • Pauseで残りが満タンに戻る
    → 「停止中だけ設定反映」エフェクトは**差分判定(前回のphaseSecondsと比較)**+[phaseSeconds, running]依存で解決。
  • ESLint: missing deps(fireNotification/playBeep/設定値など)
    → 関数は useCallback 化、エフェクト依存に網羅的に追加

7. 今回習得できた知識

  • useEffect × setInterval定石(クリーンアップ/依存)
  • 関数型アップデートで競合を避けるタイマー更新
  • SSR安全なクライアントAPIの扱い(mounted後に触る)
  • 状態遷移設計(作業→休憩→作業、ロング条件判定、Skip/Resetの分岐)
  • Web Notifications / Web Audio の実装

8. おわりに

時間を扱うUIは最初むずかしく見えるけど、やることはシンプル。
「1秒ごとに減らす → 0になったら次へ → 後片付け(clearInterval)」。この順番だけ確認すればOK。
迷ったら最小機能(開始・停止・リセット)から、動いたらサイクル→通知→音の順で少しずつ足していく。

  • useEffect は「開始」と「片付け」をセットで書く場所。
  • 何が変わったときに動くのかは依存配列でコントロール。
  • うまくいかない時は、小さい機能(開始/停止/リセット)に分解して順番にテスト。

次回(Day5)は「電卓 — 四則演算と履歴」 を作ります。

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?