refactor: EncodingConverter の手書き debounce 2 系統を useDebouncedTransform に統合 (#394) - #480
Conversation
… に統合 (#394) detect / convert の手書き useEffect + setTimeout + clearTimeout pipeline 2 系統を 汎用フック useDebouncedTransform に置換。bytes 入力・条件付き debounce(file 即時 / text 300ms)・非 string 出力に対応する。runDetect / runConvert は副作用を除いた pure function(detectFromBytes / convertFromBytes)としてモジュールスコープに抽出し、 既存テストの @/utils/encoding mock を維持。error は file I/O / detect / convert を 合流表示し、旧実装の error 相互上書きも解消した。useCodec は無変更。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
🖼️ Visual Regression Test 結果
|
レビュー (多角的観点)issue #394 の「 以下、観点別の指摘です(いずれも non-blocking)。 🟢 Low — hook 堅牢性: immediate パスが
|
PR #480 レビュー対応: - error = fileError || detectError || convertError の優先順位が未テストだった (Nit)。 convert モードで detect throw・convert 成功時に detect error が表示される陽性対照を 追加。merge を convertError 優先に戻すと fail することを実機確認済み。 - useDebouncedTransform の immediate ブランチが isPending を正規化せず、debounce→ immediate 遷移で true のまま stuck し得た (Low)。setIsPending(false) を追加し、 遷移時に false 化される陽性対照テストを併設(fix 前実装で fail を確認)。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
レビューありがとうございます。観点別に対応しました(commit 98f7a91)。 🟢 Low — immediate パスが
|
再レビュー (commit 98f7a91): LGTM ✅前回指摘 3 件すべて、commit 98f7a91 の差分で対応を確認しました。 🟢 Low — immediate パスの
|
概要
リファクタ監査 (2026-05-11) finding L-7 への対応。
EncodingConverterが持つ手書き debounce pipeline 2 系統(detect / convert)を汎用フックに統合し、debounce plumbing と state reset の散逸を解消する。Closes #394
設計判断(issue 記載との差分)
issue は「
useCodecをそのまま使う」想定だったが、EncodingConverterはuseCodecのモデルと乖離している:Uint8Array | null(activeBytes、コンポーネントがuseMemoで所有)でstringでないstringでない(detect→DetectionResult+preview / convert→Uint8Array+preview)useCodecを bytes / 非 string / 条件付き debounce 対応まで一般化すると 4 消費者(ConfigConverter / JsonXml / JsonCsv / Base64Codec)に波及するため、useCodecは無変更とし、汎用フックuseDebouncedTransform<I, R>を新設した。変更内容
src/hooks/useDebouncedTransform.ts(新規):source/transform/emptyResult/deps/{ debounceMs, immediate, fallbackError }を受け、source === nullで即時クリア、immediateで同期実行(file パス)、それ以外は debounce(再入力で前回キャンセル)、transformthrow を error 化。ジェネリックで入出力型に依存しない。src/components/tools/EncodingConverter.tsx:setTimeout/clearTimeout)とrunDetect/runConvertの setState 群を削除し、useDebouncedTransform2 回呼び出しに置換。detectFromBytes/convertFromBytesとしてモジュールスコープに抽出(既存テストのvi.mock('@/utils/encoding')を維持するため utils 側ではなくコンポーネント側に配置)。fileError || detectError || convertErrorに合流。旧実装で detect/convert effect が単一errorを相互上書きしていた latent な問題も解消。activeBytes(useMemo)とinputMethod分岐はオーケストレーション役としてコンポーネント側に残置。src/hooks/__tests__/useDebouncedTransform.test.ts(新規): immediate 同期実行 / debounce / 再入力キャンセル /source=nullクリア / throw 時 error の各ケース。検証
npm run test: 1358 passed(新規フックテスト + 既存EncodingConverter.test.tsxの debounce 集約・useMemo 安定・file reject エラー表示・convert debounce の 4 ケース全 green)node_modules/.bin/astro check: 0 errors / 0 warningsnpm run test:e2e -- encoding-converter a11y-live-region filename-sanitize: 29 passed補足
README.md/SPEC.md更新は不要。🤖 Generated with Claude Code