skip to content

On a client-side navigation between two URLs in the same nested route chain, which segments' server fetches re-run?

level: middleimportance: should knowfreq 57%

answer

  1. the router diffs old match against new
  2. unchanged parameters, reused segment data
  3. changed segments re-run on the server
  4. a data payload, not a new document

basics

~10 s

Segments whose match changed re-run; identically matched segments above them are commonly reused. The server runs the same code again but returns a serialised data payload for the changed segments, not a whole document.

solid answer

~50 s

A client-side navigation re-matches the new URL and compares it with the current one segment by segment. Segments whose matched parameters are unchanged — the shared outer layout, say — usually keep their existing data, while the segments that changed have their data functions invoked again on the server. That is what makes moving between sibling detail pages cheap: only the leaf's data is refetched. The response is not a document; it is a serialised payload for the changed segments that the client renders into the page it already has. Frameworks differ in how aggressive the reuse is — some re-run every matched segment on each navigation, some reuse by segment and parameters, some let a route say when it should re-run — so never assert that an unchanged parent's data is refreshed, and never assume it is stale forever either.

go deeper

for a junior

Recall that a client navigation re-matches the URL and asks the server only for what changed, and that the page is patched rather than replaced with a new document.

for a middle

Explain the per-segment diff: unchanged matched parameters make a segment reusable, changed ones force a re-run, and the response is a serialised payload the live page applies.

for a senior

Show you can prove which segments refetched, and connect over-reuse to a stale-after-write report and under-reuse to navigations that cost as much as a cold load.

for a principal

Judge the default: aggressive reuse buys snappy navigation and risks stale outer data, while refetching everything buys freshness at a per-navigation cost. Decide which routes deserve which, and how the team encodes it.

## What a client-side navigation actually does On a full document request the browser throws the current page away. On a **client-side navigation** it does not: the router intercepts the intent, matches the new URL, decides what data it is missing, asks the server for exactly that, and re-renders the parts of the tree that changed. The URL in the address bar is updated through the History API rather than by loading a document. That gives the router a comparison it did not have on first load: *the old match versus the new match*, segment by segment. ## The segment-by-segment comparison Consider a chain of three matched segments — an outer section, a collection, and a detail view — and a navigation from one detail URL to a sibling detail URL. | Segment | Match before | Match after | Typical treatment | |---|---|---|---| | Outer section | identical | identical | data reused, not refetched | | Collection | identical | identical | data reused, not refetched | | Detail | one identifier | a different identifier | data function re-runs | The rule of thumb is that a segment whose matched parameters are unchanged is a candidate for reuse, and a segment whose parameters changed must be refetched because its data is a function of those parameters. This is why the outer chrome of an application does not flash or refetch when you move between items inside it. There are qualifications worth stating out loud: - **Reuse is an optimisation, not a law.** Some frameworks re-invoke every matched segment's data function on every navigation, favouring freshness over round trips. Some reuse by default and offer an explicit way to force a re-run. Some let each route declare the condition under which it should re-run. - **An unchanged parent can still need fresh data.** If a write in the detail view changed something the collection displays, reuse shows a stale count. Invalidating those copies is a separate mechanism with its own rules; what belongs here is knowing that reuse is why the stale value survived. - **A full reload is the reset.** Anything reused in memory is gone; every matched segment fetches again from scratch. ## What comes back over the wire The same server-side code runs, but the response is different in kind. On a document request the output is HTML. On a client navigation it is a **serialised data payload** — the data (or the rendered description of the changed subtree, depending on the framework) for the segments that changed, in a format the already-running client can apply to the existing page. Practical consequences: 1. The payload is typically far smaller than a document, because unchanged layouts are not resent. 2. The data still has to be serialisable, exactly as on first render — same constraint, same reason. 3. The route's server code is still the only place the fetch runs; the browser did not gain direct access to the data source. 4. Because no new document is delivered, a normal HTTP status line is not how failures present themselves to the user — the payload has to carry the failure so the client can render the right state. ## Why this matters in practice The reuse boundary is the single biggest lever on how a navigation *feels*. If every segment refetches, moving between two rows in a list costs the whole route's data phase every time. If only the leaf refetches, it costs one read. Two failure modes follow directly: - **Too much reuse** shows stale outer data after a write, and the fix belongs to invalidation, not to the fetch. - **Too little reuse** makes every navigation as expensive as a cold load, and the fix is to check what the framework considers "changed" — a parent whose data function reads something request-specific may be treated as changed on every navigation. ## How to answer it well Say the comparison out loud: match the new URL, diff it against the old one per segment, re-run the changed segments' data functions on the server, reuse the rest, and apply a serialised payload to the live page. Then add the honest caveat that the reuse policy varies between frameworks and can usually be overridden per route — that caveat is what distinguishes someone who has read a single product's documentation from someone who understands the mechanism.

  • Why does an unchanged parent segment sometimes show stale data after a write in a child?
    Because its match did not change, so its data was reused rather than refetched. The write invalidated the underlying truth, not the reused copy. Fixing it means telling the framework that this route's data is no longer valid, which is an invalidation concern; the reuse itself is working as designed.
  • If the fetch still runs on the server during a client navigation, what has actually been saved?
    The document round trip and the re-render of everything unchanged. The browser keeps its JavaScript, its layout and its component state; only the changed segments' data is requested and applied. The saving is in bytes transferred and work repeated, not in where the fetch executes.
  • How would you confirm which segments refetched on a given navigation?
    Watch the network for the navigation request and inspect the payload: it names or shapes only the segments the framework decided to refresh. Correlating that with server-side logging inside each segment's data function tells you exactly which ones were invoked and which were reused.

saying these in an interview costs you the question

  • Thinks client navigation never contacts the server for route data
  • Assumes every segment always refetches on every navigation
  • Believes the response is a full HTML document swapped in
  • Says reused data must be stale and therefore useless
  • Expects route data to be restored from the browser history entry