From aa4214613ca42c0f2ee3b5d2d5d1a24630c884b9 Mon Sep 17 00:00:00 2001 From: mortezaei Date: Sun, 30 Aug 2026 07:14:09 +0330 Subject: [PATCH] refactor(ui): synchronize profile redirection with fetch status Update client-side redirection logic across multiple routes to ensure routing decisions are only made after the profile data has been successfully fetched from the server. This prevents premature or incorrect redirects based on stale or incomplete hydrated data. - Add `isFetched` check to `useEffect` guards in candidate-contact, finding-match, new-match, request-accepted, and request-sent clients - Update `QuestionsListClient` to wait for `isProfileFetched` before triggering redirects - Clean up dependency arrays to include new fetch status variables --- src/app/candidate-contact/candidate-contact-client.tsx | 4 ++-- src/app/finding-match/finding-match-client.tsx | 7 +------ src/app/new-match/new-match-client.tsx | 9 ++------- src/app/questions-list/questions-list-client.tsx | 4 ++-- src/app/request-accepted/request-accepted-client.tsx | 5 +---- src/app/request-sent/request-sent-client.tsx | 5 +---- 6 files changed, 9 insertions(+), 25 deletions(-) diff --git a/src/app/candidate-contact/candidate-contact-client.tsx b/src/app/candidate-contact/candidate-contact-client.tsx index 16f1961..fa0d9e2 100644 --- a/src/app/candidate-contact/candidate-contact-client.tsx +++ b/src/app/candidate-contact/candidate-contact-client.tsx @@ -54,14 +54,14 @@ export default function CandidateContactClient() { }); useEffect(() => { - if (!profile) { + if (!profile || !isFetched) { return; } const targetPath = getSubmitPath(profile); if (targetPath !== "/candidate-contact") { router.replace(localizePath(targetPath, locale)); } - }, [profile, router, locale]); + }, [profile, isFetched, router, locale]); // Signal Flutter to lift its loading cover immediately on mount useHabibWebReady(true); diff --git a/src/app/finding-match/finding-match-client.tsx b/src/app/finding-match/finding-match-client.tsx index d330b89..2d7b85f 100644 --- a/src/app/finding-match/finding-match-client.tsx +++ b/src/app/finding-match/finding-match-client.tsx @@ -47,12 +47,7 @@ export default function FindingMatchClient() { }); useEffect(() => { - if (!profile) { - return; - } - // Don't bounce away from finding-match if we only have preliminary initialData - // with pending_info before the fresh server query finishes - if (!isFetched && profile.status === "pending_info") { + if (!profile || !isFetched) { return; } const targetPath = getSubmitPath(profile); diff --git a/src/app/new-match/new-match-client.tsx b/src/app/new-match/new-match-client.tsx index 921fcda..4db945e 100644 --- a/src/app/new-match/new-match-client.tsx +++ b/src/app/new-match/new-match-client.tsx @@ -597,19 +597,14 @@ export default function NewMatchClient() { fullProfileObject: profile, }); - if (!profile) { - return; - } - // Don't redirect based on stale native-injected initialData that may be - // missing active_case; wait for the first real server response. - if (!isFetched && profile.status === "in_case" && !profile.active_case) { + if (!profile || !isFetched) { return; } const targetPath = getSubmitPath(profile); if (targetPath !== "/new-match") { router.replace(localizePath(targetPath, locale)); } - }, [profile, locale, router, isLoading, isFetched, isError]); + }, [profile, locale, router, isFetched]); // Signal Flutter to lift its loading cover immediately on mount useHabibWebReady(true); diff --git a/src/app/questions-list/questions-list-client.tsx b/src/app/questions-list/questions-list-client.tsx index d49ab79..fc2ef79 100644 --- a/src/app/questions-list/questions-list-client.tsx +++ b/src/app/questions-list/questions-list-client.tsx @@ -126,10 +126,10 @@ export default function QuestionsListClient() { }, [profile, profileTargetPath]); useEffect(() => { - if (isProfileRedirecting && profileTargetPath) { + if (isProfileFetched && isProfileRedirecting && profileTargetPath) { router.replace(localizePath(profileTargetPath, locale)); } - }, [isProfileRedirecting, locale, profileTargetPath, router]); + }, [isProfileFetched, isProfileRedirecting, locale, profileTargetPath, router]); // Background prefetch user's geo country code so phone question is pre-warmed useEffect(() => { diff --git a/src/app/request-accepted/request-accepted-client.tsx b/src/app/request-accepted/request-accepted-client.tsx index 1e43a19..a345e85 100644 --- a/src/app/request-accepted/request-accepted-client.tsx +++ b/src/app/request-accepted/request-accepted-client.tsx @@ -255,10 +255,7 @@ export default function RequestAcceptedClient() { const contactSharedAtStr = profile?.active_case?.contact_shared_at; useEffect(() => { - if (!profile || noContactReportedSuccess) { - return; - } - if (!isFetched && profile.status === "in_case" && !profile.active_case) { + if (!profile || !isFetched || noContactReportedSuccess) { return; } const targetPath = getSubmitPath(profile); diff --git a/src/app/request-sent/request-sent-client.tsx b/src/app/request-sent/request-sent-client.tsx index d3e80b8..797714d 100644 --- a/src/app/request-sent/request-sent-client.tsx +++ b/src/app/request-sent/request-sent-client.tsx @@ -45,10 +45,7 @@ export default function RequestSentClient() { }); useEffect(() => { - if (!profile) { - return; - } - if (!isFetched && profile.status === "in_case" && !profile.active_case) { + if (!profile || !isFetched) { return; } const targetPath = getSubmitPath(profile);