背景
PR #6013(ディープリンクで短縮ID (?id=<code>) から経路を解決できるようにする)のレビューで CodeRabbit から「Outside diff range」コメントとして指摘された問題。本 PR では別 Issue として切り出して対応する方針のため、ここに起票する。
レビューコメント原文: #6013 (review)
問題
src/hooks/useDeepLink.ts の handleUrl で、resolver 経路(?id=<code>)の解決中に例外が発生すると setResolverError(err) が走り、useDeepLink() の戻り値の error に反映される。
しかし、その後ユーザーが別のディープリンクを開いた場合、handleUrl のどこでも resolverError をクリアしていないため、stale なエラーが残り続ける。後続の成功ケース(resolver 経路自体の再試行成功、あるいは ?sids=... / ?sgid=...&lid=... の legacy 経路)でも、hook の error は古い resolver エラーを返したままになる。
Apollo 由来の fetchStationsByLineGroupIdError / fetchStationsByLineIdError / fetchStationsByIdsError は Apollo Client が内部で次回クエリ呼び出し時にリセットしてくれるが、resolverError は自前 useState で保持しているため、明示的にクリアしないと残り続ける。
再現手順
- 不正な短縮 ID(DB に存在しない
?id=missing など)でアプリを開く → resolver が 404 を投げ resolverError がセットされる
- 同じセッション中に別のリンク(例:
?lid=999&sgid=1&dir=0)を開く → legacy 経路で正常に解決される
- しかし
useDeepLink().error には 1 のエラーが残ったまま
提案
handleUrl の冒頭、もしくは resolver 経路の try 直前 + 成功パスで setResolverError(null) を呼び、毎回エラー状態をリセットする。最も単純なのは冒頭でクリアする案。
const handleUrl = useCallback(
async (url: string) => {
const parsed = Linking.parse(url);
if (!parsed.queryParams) {
return;
}
+ setResolverError(null);
const { sgid, dir, lgid, lid, sids, skips, id, auto, theme } =
parsed.queryParams;
setResolverError(null) を冒頭でクリアすると以下を担保できる:
- 同一 hook インスタンス内で resolver 経路 → legacy 経路と続けた場合に、legacy 経路の
error 値が stale な resolver エラーを返さない
- resolver 経路自体を再試行して成功したケースでも
error がクリアされる
副作用として、parsed.queryParams が falsy で早期 return する場合は resolverError をクリアしないことになるが、URL 構造が壊れているだけの早期 return は本機能の動作主旨に影響しないため許容範囲。
受け入れ条件
関連
背景
PR #6013(ディープリンクで短縮ID
(?id=<code>)から経路を解決できるようにする)のレビューで CodeRabbit から「Outside diff range」コメントとして指摘された問題。本 PR では別 Issue として切り出して対応する方針のため、ここに起票する。レビューコメント原文: #6013 (review)
問題
src/hooks/useDeepLink.tsのhandleUrlで、resolver 経路(?id=<code>)の解決中に例外が発生するとsetResolverError(err)が走り、useDeepLink()の戻り値のerrorに反映される。しかし、その後ユーザーが別のディープリンクを開いた場合、
handleUrlのどこでもresolverErrorをクリアしていないため、stale なエラーが残り続ける。後続の成功ケース(resolver 経路自体の再試行成功、あるいは?sids=.../?sgid=...&lid=...の legacy 経路)でも、hook のerrorは古い resolver エラーを返したままになる。Apollo 由来の
fetchStationsByLineGroupIdError/fetchStationsByLineIdError/fetchStationsByIdsErrorは Apollo Client が内部で次回クエリ呼び出し時にリセットしてくれるが、resolverErrorは自前useStateで保持しているため、明示的にクリアしないと残り続ける。再現手順
?id=missingなど)でアプリを開く → resolver が 404 を投げresolverErrorがセットされる?lid=999&sgid=1&dir=0)を開く → legacy 経路で正常に解決されるuseDeepLink().errorには 1 のエラーが残ったまま提案
handleUrlの冒頭、もしくは resolver 経路のtry直前 + 成功パスでsetResolverError(null)を呼び、毎回エラー状態をリセットする。最も単純なのは冒頭でクリアする案。const handleUrl = useCallback( async (url: string) => { const parsed = Linking.parse(url); if (!parsed.queryParams) { return; } + setResolverError(null); const { sgid, dir, lgid, lid, sids, skips, id, auto, theme } = parsed.queryParams;setResolverError(null)を冒頭でクリアすると以下を担保できる:error値が stale な resolver エラーを返さないerrorがクリアされる副作用として、
parsed.queryParamsが falsy で早期 return する場合はresolverErrorをクリアしないことになるが、URL 構造が壊れているだけの早期 return は本機能の動作主旨に影響しないため許容範囲。受け入れ条件
handleUrl実行でresolverErrorが前回値を引きずらないuseDeepLink().errorがnullになることを単体テストで検証関連