Skip to content

Commit db6738f

Browse files
committed
fix(view-page): scope fetched view lookup state by route
1 parent 68f0a06 commit db6738f

File tree

1 file changed

+34
-4
lines changed

1 file changed

+34
-4
lines changed

src/pages/views/ViewPage.tsx

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,48 @@ export function ViewPage() {
2424
// `id` is directly available from the route — no need to duplicate it in state.
2525
// `fetchedId` holds the resolved ID when we had to look it up by name/namespace.
2626
const [fetchedId, setFetchedId] = useState<string | undefined>();
27+
const [fetchedLookupKey, setFetchedLookupKey] = useState<
28+
string | undefined
29+
>();
2730
const [isLoading, setIsLoading] = useState(false);
2831
const [error, setError] = useState<unknown | null>(null);
2932

33+
const lookupKey = name
34+
? namespace
35+
? `${namespace}/${name}`
36+
: name
37+
: undefined;
38+
39+
// Only use fetched IDs for the route that produced them.
40+
const scopedFetchedId =
41+
lookupKey && fetchedLookupKey === lookupKey ? fetchedId : undefined;
42+
3043
// Derived: prefer the direct `id` param; fall back to whatever we fetched.
31-
const viewId = id ?? fetchedId;
44+
const viewId = id ?? scopedFetchedId;
3245

3346
useEffect(() => {
3447
// When a direct `id` is present there is nothing to fetch.
35-
if (id) return;
48+
// Clear lookup-only state so route transitions cannot leak stale values.
49+
if (id) {
50+
setFetchedId(undefined);
51+
setFetchedLookupKey(undefined);
52+
setIsLoading(false);
53+
setError(null);
54+
return;
55+
}
3656

37-
if (!name) {
57+
if (!name || !lookupKey) {
58+
setFetchedId(undefined);
59+
setFetchedLookupKey(undefined);
60+
setIsLoading(false);
3861
setError("No view identifier provided");
3962
return;
4063
}
4164

65+
// Reset stale lookup value for the previous route while this route resolves.
66+
setFetchedLookupKey(lookupKey);
67+
setFetchedId(undefined);
68+
4269
// AbortController lets us cancel the in-flight request if the component
4370
// unmounts or the route params change before the response arrives,
4471
// preventing stale-closure / race-condition state updates.
@@ -64,15 +91,18 @@ export function ViewPage() {
6491
if (controller.signal.aborted) return;
6592

6693
if (!resolved) {
94+
setFetchedId(undefined);
6795
setError(
6896
`View not found: ${namespace ? `${namespace}/${name}` : name}`
6997
);
7098
return;
7199
}
72100

101+
setFetchedLookupKey(lookupKey);
73102
setFetchedId(resolved);
74103
} catch (err) {
75104
if (controller.signal.aborted) return;
105+
setFetchedId(undefined);
76106
setError(err ?? "Failed to load view");
77107
} finally {
78108
if (!controller.signal.aborted) {
@@ -84,7 +114,7 @@ export function ViewPage() {
84114
fetchViewId();
85115

86116
return () => controller.abort();
87-
}, [id, namespace, name]);
117+
}, [id, namespace, name, lookupKey]);
88118

89119
if (isLoading) {
90120
return (

0 commit comments

Comments
 (0)