feat(career): 未保存離脱ガードを全ページ横断に拡張#314
Conversation
職務経歴書に未保存があるとき、GitHub連携/ブログ連携ページに移動した後でも × 閉じ・リロード時にブラウザ標準の離脱確認が出るようにする。 これまで beforeunload ガードは職務経歴書フォームのマウント中のみ有効で、 別ページへ移ると未保存があっても発火しなかった。判定を Redux formCache 基準に 変え、App 直下の CareerUnsavedGuard へ移設して全ページで有効化する。 - CareerUnsavedGuard を追加(formCache を購読し dirty 判定、描画は null) - App に組み込み、CareerResumeForm 内の重複ガード呼び出しを削除 - ログイン済みのみ対象(未ログインは baseline=null で dirty.any 常に false) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 45 minutes and 33 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe PR refactors unsaved-changes warning behavior by extracting logic from ChangesCareer Form Unsaved Changes Guard
🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@frontend/src/components/CareerUnsavedGuard.tsx`:
- Around line 20-22: The code currently force-casts cache?.form and
cache?.baseline to CareerFormState which can crash if the stored unknown payload
is stale or corrupt; update the CareerUnsavedGuard to validate the cached values
before using them by adding a runtime type guard or safe parser (e.g.,
isCareerFormState(value)) and only assign form = validated value or fallback to
createInitialCareerForm(), and set baseline = validated baseline or null; ensure
useCareerDirty is always called with valid CareerFormState or null to prevent
nested-access crashes and reference the existing symbols form, baseline,
createInitialCareerForm, and useCareerDirty when implementing the checks.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 731e8704-7301-4db7-8010-e1d007967f3f
📒 Files selected for processing (4)
frontend/src/App.tsxfrontend/src/components/CareerUnsavedGuard.test.tsxfrontend/src/components/CareerUnsavedGuard.tsxfrontend/src/components/forms/CareerResumeForm.tsx
💤 Files with no reviewable changes (1)
- frontend/src/components/forms/CareerResumeForm.tsx
CareerUnsavedGuard が formCache の unknown 値を CareerFormState に キャストしていた箇所を、isCareerFormState による実行時検証に置き換える。 useCareerDirty / buildClean は配列・文字列フィールドへネストアクセスするため、 不正・欠損値が入っていた場合のクラッシュを防ぎ、安全側(未保存なし)に倒す。 - isCareerFormState 型ガードを追加(先頭構造の検証) - 不正値は form=空フォーム / baseline=null にフォールバック - 壊れたキャッシュ値でクラッシュしないことの回帰テストを追加 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
概要
職務経歴書に未保存の変更がある状態で GitHub連携 / ブログ連携ページへ移動した後でも、× 閉じ・リロード時にブラウザ標準の離脱確認ダイアログが出るようにします。
背景・課題
直前の PR #313 で導入した
beforeunloadガードは、職務経歴書フォーム(CareerResumeForm)がマウントされている間しか有効でなく、別ページ(GitHub/ブログ)へ移動するとフォームがアンマウントされてガードが外れていました。そのため「未保存のまま別ページに移動 → そこからタブを閉じる/リロード」でデータが失われても警告が出ませんでした。変更内容
CareerUnsavedGuardを追加: 未保存判定をフォームのローカル state ではなく ReduxformCache(in-app 遷移をまたいで保持される)から行うコンポーネント。App直下に常設し、どのページにいても職務経歴書の未保存を監視する。描画はnullのため周辺ツリーへ再描画は波及しない。App.tsx:<CareerUnsavedGuard isAuthenticated={user !== null} />を組み込み。CareerResumeForm.tsx: フォーム内のuseUnsavedChangesWarning呼び出しを削除し、ガードを App 側に一本化(二重登録の回避)。dirty.anyが常に false =対象外。入力は sessionStorage に自動退避される)。検証
make test-frontend… 296 pass(CareerUnsavedGuardの 3 ケース追加: ログイン済み×未保存=抑止 / 未ログイン=非抑止 / 未保存なし=非抑止)make lint-frontend/make lint-frontend-messages… cleanmake build-frontend… 型エラーなしnpm run test:e2e)… 30 pass(既存ナビゲーションに回帰なし)🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Tests