You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/blog/tanstack-router-navigation-lifetimes.md
+11-7Lines changed: 11 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,13 +16,17 @@ From application code, a navigation looks almost too simple:
16
16
awaitrouter.navigate({ to: '/account' })
17
17
```
18
18
19
-
One call, one promise, one destination.
19
+
Now let's imagine a slightly more complex scenario.
20
20
21
-
Now imagine that the user hovers the link first. The router starts preloading `/account`. They click while its loader is still running, so the navigation joins the work that the hover already started.
Before it finishes, they click `/settings`. That route has a layout and an index child, with a loader on each. The layout loader fails, but the index loader redirects to `/login`.
24
-
25
-
Meanwhile, the `/account` loader is still useful to the preload. Its result can enter the cache even though `/account` is no longer where the user is going. The router eventually publishes `/login`, then waits for the framework to catch up.
23
+
1. The user hovers a link, and the router starts preloading `/account`
24
+
2. They click the link while its loader is still running, so the navigation joins the work that the hover already started
25
+
3. While it's still loading, they click `/settings`, which has many parallel `loader` calls to run
26
+
4. The layout loader errors, but the index loader redirects to `/login`
27
+
5. Meanwhile, the `/account` loader settles. The user is no longer going to `/account` but its result can enter the cache
28
+
6. The router eventually publishes `/login` but its content suspends
29
+
7. Finally, the suspense resolves and the framework renders the `/login` page
26
30
27
31
<figure>
28
32
<imgsrc="/blog-assets/tanstack-router-loading-lifetimes/nav-orchestra_simple-scenario.svg"style="width:100%"alt="A timeline where an account preload is joined by a navigation, a later settings navigation starts layout and index loaders, the index loader redirects to login, account data also enters the cache, and the framework acknowledges login after publication">
@@ -35,7 +39,7 @@ Which result is allowed to reach the page? Which loader should be canceled? Does
35
39
36
40
Those questions do not have one shared answer.
37
41
38
-
We learned this the hard way. [A rewrite of TanStack Router's match-loading core](https://github.com/TanStack/router/pull/7805) grew around dozens of linked reports and patches across preloading, redirects, caching, pending UI, SSR, and more. They looked unrelated, but most crossed the same boundary: one part of the router was answering a question that belonged to another.
42
+
We learned this the hard way. [A rewrite of TanStack Router's route loading core](https://github.com/TanStack/router/pull/7805) grew around dozens of linked reports and patches across preloading, redirects, caching, pending UI, SSR, and more. They looked unrelated, but most crossed the same boundary: one part of the router was answering a question that belonged to another.
39
43
40
44
The new model assigns separate owners to publishing, route outcomes, loader work, and rendering. There is still one `navigate()` call at the API boundary, but there is no single owner of everything inside it.[^architecture]
41
45
@@ -114,7 +118,7 @@ A loader flight can also outlive its promise. An accepted or cached match may ke
114
118
115
119
### A Loader Outcome Is Not a Route Outcome
116
120
117
-
A rejected loader promise is a local fact. It is not automatically a decision to render an error page. Other loaders that already started may still produce control flow, such as a redirect or not-found result, that changes the meaning of the whole attempt.
121
+
A rejected loader promise is a local fact. It is not automatically a decision to render an error page. Other loaders that already started may still produce control flow, such as a redirect, that changes the meaning of the whole attempt.
118
122
119
123
The router therefore normalizes individual settlements and returns them to the lane. The lane reducer considers the outcomes together and selects one semantic result. Only that reduced result can be projected into publishable matches.
0 commit comments