skip to content

Client-Side Routing

How a URL becomes a rendered screen with no page load: a route table, nested outlets, navigation, guards and lazily loaded route code. Interviewers start here because the URL is shared state.

on this pageshow

explore

questions

page 1 of 2

In a client-side router, what is a route guard and what verdicts can it return for a pending navigation?

level: juniorimportance: must knowfreq 68%

answer

  1. stands in the corridor, not the room
  2. matched, then guarded, then rendered
  3. three verdicts, not two
  4. usually asynchronous, awaits the session
  5. hiding a route enforces nothing

basics

~20 s

A route guard is a check the router runs before committing a navigation. It can let the navigation proceed, redirect it elsewhere such as a sign-in screen, or cancel it and leave the current screen up.

solid answer

~50 s

A guard is a function attached to a route table entry that the router consults while a navigation is still pending — after it has matched the URL to a chain of routes, but before the target route's components render. It receives a description of the attempted navigation (the target path, its parsed parameters, the location being left) and returns one of three verdicts: proceed, redirect to a different route, or cancel so the current screen and URL stay exactly as they are. Guards are normally asynchronous, because the answer usually depends on a session that is still being restored, so the router holds the previous screen or shows a pending state while it waits. The framing that matters: a guard is user experience, not enforcement — the route table and the guard both ship to the browser, so the server that owns the data still has to check every request.

go deeper

for a junior

Be able to define a guard in one sentence and name its three outcomes: proceed, redirect, cancel. Know that it runs before the protected screen renders, not inside it.

for a middle

Explain where the guard sits in the navigation pipeline — after URL matching, before commit and render — and why it usually has to be asynchronous while a session is being restored.

for a senior

Show that you treat the guard as navigation experience while the server enforces access, and that cold-start navigations, pending screens and superseded navigations are part of your design.

for a principal

Frame the guard as a product decision about what a user is offered, and insist that access policy has exactly one owner; a second copy of the rules in the client bundle is a drift risk, not a safeguard.

## What a route guard is A **route guard** is a function the router consults while a navigation is still in flight, before the target screen exists. It is attached to an entry in the route table — a leaf route, or a route that other routes nest under — and it is handed a description of the attempted navigation: the target path, its parsed parameters, usually the query and fragment, the location being left, and often a hint about how the navigation started (an intercepted link click, a programmatic navigation, a history traversal, or the first match of a URL that arrived in the address bar). It renders nothing. It answers. The borrowed name is the accurate mental model: the guard stands in the corridor, not inside the room. Everything that makes a guard useful follows from *where* it runs rather than from what it checks. ## Where a guard sits in the navigation pipeline A client router turns a URL into a screen in ordered steps: 1. **A navigation is requested** — an intercepted link click, a programmatic navigation, a Back or Forward traversal, or the initial load of the document's URL. 2. **The URL is matched** against the route table, producing a matched chain from the outermost layout route down to the leaf. 3. **The guards on that chain run**, outermost first, and the router waits for their verdicts. 4. **Route code and route data resolve** — a lazily loaded module for the segment, whatever data a loader or resolver is responsible for. 5. **The navigation commits** — the history entry and the address bar update, and the target's components render into their outlets. The entire value of a guard is that step 3 happens before step 5. Nothing in the target has rendered, nothing below it has started a request, and the address bar still shows the route the user is on. If the verdict is a redirect, the user never sees the protected path appear at all. ## The three verdicts | Verdict | What the router does | What the user sees | |---|---|---| | **Proceed** | continues the pending navigation into steps 4 and 5 | the target screen, normally | | **Redirect** | abandons the pending target and navigates to a different route | sign-in, a forbidden notice, or a default screen | | **Cancel** | drops the navigation entirely | the current screen, unchanged, URL untouched | Cancel and redirect are not interchangeable. Cancelling is right when the user should stay where they are and the app has nowhere better to send them; the URL must not change, which matters because a half-applied navigation — new URL, old screen — is a bug users report as "the page is wrong". Redirecting is right when there is a meaningful destination: an anonymous visitor belongs on sign-in, and a signed-in user without the required role belongs on a screen that explains that, not back on sign-in they already passed. ## Guards are usually asynchronous - The verdict normally depends on a **session** that is still being restored, so the guard returns something the router awaits rather than a plain boolean. - While the router waits it **keeps the previous screen** on screen, often with a pending indicator. On a cold start there is no previous screen, so a neutral boot screen covers the gap. - A newer navigation can **supersede** a pending one, so a router discards a stale verdict instead of acting on it; work the guard started should be abandoned with it. - Several guards in one chain should **await one shared session resolution** rather than each starting its own restore. ## Common shapes A guard is usually one function on a route entry, or a small **list** of functions on that entry that narrow in order: is there a session at all, is this account a member of the workspace, does it hold the role this route needs. Some codebases instead express the check as a component that wraps the protected screen. That shape is reachable but weaker, because a component runs *inside* step 5 rather than before it. ## A guard is user experience, not enforcement - The route table, the guard and the permission data it reads all **ship to the browser**, where they can be read and edited. - Everything the protected screen would have shown arrives from a **server request**, and only the server can decide whether the caller may have it. - Hiding a route hides a *screen*, not the *data*; a request issued by hand reaches the same endpoint with the same credentials. - The honest division of labour: the guard keeps a user out of a screen that would only fail, and the server rejects every request it ought to reject — on every request, not once at sign-in. ## What interviewers listen for - That you place the guard in the pipeline (matched, then guarded, then rendered) rather than describing it as "a check on the page". - That you name all three verdicts, and can say when cancelling beats redirecting. - That you treat "session not known yet" as its own state rather than as signed-out. - That you volunteer the enforcement sentence without being prompted for it.

  • What does a guard actually receive about the navigation it is judging?
    A description of the attempted target — the path, its parsed parameters, usually the query and fragment — plus the location being left and often how the navigation started. That is enough to decide, and enough to record where the user wanted to go so a sign-in flow can bring them back to it.
  • When is cancelling a navigation the right verdict instead of redirecting?
    When the user should simply stay put and there is no better destination: the current screen and URL remain untouched. Redirecting replaces the pending target with a different route, so the user lands somewhere new. Picking redirect when you mean cancel changes the URL and strands the user away from their context.
  • Does a guard run when a URL is typed straight into the address bar?
    Yes — the first match is a navigation like any other, and it is the case guards get wrong most often. No session has been restored yet and there is no previous screen to hold while the guard waits, so the app needs a neutral pending screen for exactly that moment.

saying these in an interview costs you the question

  • Thinks a guard secures data rather than shaping navigation
  • Believes hiding a route from the table prevents access to its data
  • Assumes guards only run on full page loads, not in-app navigations
  • Treats the session as known synchronously when the guard runs
  • Names only allow and deny, missing the redirect verdict
open as a page

In a client-side router, what does it mean for a route entry to name a module loader instead of a component?

level: juniorimportance: must knowfreq 72%

basics

~20 s

The table stores a function that fetches that route's code on demand rather than a component the start-up bundle already contains. The router calls it on the first navigation that matches, waits, then renders what it resolves to.

open as a page

In a client-side router with nested routes, what does the outlet a parent route renders actually do?

level: juniorimportance: must knowfreq 66%

basics

~20 s

An outlet is a marked position a parent route's component renders, and the router mounts whichever child route matched the deeper part of the URL into that position. The parent draws the shared chrome around it.

open as a page

In a client-rendered application, which parts of a screen's state belong in the URL and which must not?

level: juniorimportance: must knowfreq 78%

basics

~20 s

The URL should carry state a user could reasonably share, bookmark or reach again with the Back button: the view, the selected entity, filters, sort and page. Transient interface state, secrets and large payloads stay in memory.

open as a page

Why does a wrapper that renders a protected screen and then redirects flash protected content, and what prevents it?

level: middleimportance: must knowfreq 64%

basics

~20 s

Because the redirect is scheduled from a side effect that runs only after the wrapper's subtree has rendered and its data requests have gone out. Deciding in the router's navigation step, before the target renders, removes the flash.

open as a page

While a lazily loaded route's code is in flight, what decides whether the user keeps the previous screen or sees a fallback?

level: middleimportance: must knowfreq 60%

basics

~10 s

Who owns the pending period. A router that holds the navigation keeps the old screen mounted with a progress cue; one that commits the new branch immediately shows the nearest async boundary's fallback instead.

open as a page

Why does a matched route parameter arrive as text, and what must a route entry do before a screen uses it?

level: middleimportance: must knowfreq 70%

basics

~20 s

A URL is text and a pattern checks only path shape, so every captured value is untrusted input. The route entry converts it into typed data once, at that boundary, and takes a failure branch when conversion fails.

open as a page

When the user navigates between two sibling child routes under the same parent, what does the router keep mounted?

level: middleimportance: must knowfreq 60%

basics

~20 s

Every level the two matches share stays mounted and is updated in place, so the parent's component instance and its state survive. Only the deepest level that differs is torn down and replaced inside its outlet.

open as a page

How should a router stop a user leaving a form with unsaved changes, and what can it not stop?

level: seniorimportance: must knowfreq 56%

basics

~20 s

Register a blocker while the form is dirty: the router consults it before committing any navigation it controls, holding the transition open until the user answers. A real document unload can only be asked about, never blocked.

open as a page

What is structurally wrong when a nested-route app's shared sidebar collapses, loses its scroll and reloads its data on every section switch?

level: seniorimportance: must knowfreq 55%

basics

~20 s

The chrome is not on a level both URLs share, so it is rebuilt on each navigation — usually because each screen renders its own copy, or because its level sits at or below the point where the two matches diverge.

open as a page

In a client router's route table, what does a catch-all segment match that a single dynamic segment cannot?

level: juniorimportance: should knowfreq 56%

basics

~10 s

A dynamic segment matches exactly one path segment and stops at the next separator. A catch-all matches the whole remainder of the path, separators included, and hands that leftover over as the captured value.

open as a page

A guard reads a session that is still loading and bounces signed-in users to sign-in on reload; why, and what fixes it?

level: middleimportance: should knowfreq 58%

basics

~20 s

The guard collapses "not known yet" into "signed out". A session restored asynchronously is still unresolved during the first navigation after a reload, so the guard must await one shared resolution and model three states, not a boolean.

open as a page

For preloading, how does a lazily loaded route differ from a lazily loaded component rendered inside that route?

level: middleimportance: should knowfreq 44%

basics

~20 s

A route's loader sits in the route table, so a URL alone names the modules the next screen needs. A lazy component's loader is reached only by rendering its parent, so no link can preload it.

open as a page

How does a router preload a lazily loaded route's code before the click, and which signals typically trigger it?

level: middleimportance: should knowfreq 56%

basics

~20 s

It resolves a link's URL through the route table, then calls the matched entries' loaders early without navigating. Typical triggers are pointer hover or touch start, keyboard focus, the link entering the viewport, and idle time.

open as a page

In a nested route table, how does a parent entry's pattern constrain which child entries can match a URL?

level: middleimportance: should knowfreq 45%

basics

~20 s

The parent consumes a path prefix, so its children are matched only against the remainder, and only if the parent matched at all. A failing parent skips its whole branch, and its captured parameters stay visible below.

open as a page

Why do client routers model not-found as an entry in the route table rather than a render-time fallback?

level: middleimportance: should knowfreq 48%

basics

~20 s

Failing to match is a routing outcome, not a rendering detail. An entry is reached when matching fails or a matched entry rejects its value, before any route's work runs, and one place then owns the missing-page screen.

open as a page

A client-side router redirects by pushing a new history entry. Why does pressing Back bounce the user forward again?

level: middleimportance: should knowfreq 54%

basics

~20 s

Pushing leaves the pre-redirect address on the stack, so Back lands on it, the same condition redirects again, and the user is pushed forward. A navigation that corrects the current location must replace that entry, not add one.

open as a page

In a nested route table, what does an index child route do, and what does a pathless layout route do?

level: middleimportance: should knowfreq 52%

basics

~20 s

Both add no URL segment. An index child fills its parent's outlet when the URL stops at the parent. A pathless layout route adds a component level with its own chrome and boundaries while leaving its children's URLs untouched.

open as a page

When designing a screen's address, what do the path, the query string and the fragment each carry?

level: middleimportance: should knowfreq 60%

basics

~20 s

The path carries identity - which screen and which entity. The query string carries refinements of that identity, such as search, filters, sort and page. The fragment carries client-only position or state and is never sent to the server.

open as a page

How do you serialize a screen's filters, sort and page into an address so a reload rebuilds the same view?

level: middleimportance: should knowfreq 52%

basics

~20 s

Pick one short text spelling per value, omit anything equal to its default, emit keys in a fixed order, and make parsing the exact inverse, so a reload reproduces the screen and one state always produces one address.

open as a page

In a nested route chain where a parent and its child both carry guards, what order runs and why does it matter?

level: seniorimportance: should knowfreq 46%

basics

~20 s

Routers normally run a matched chain's guards from the outermost route inward, stopping at the first redirect or cancel. A parent can establish the session and a child narrow by role — but only for chains that include that parent.

open as a page

After a guard redirects to sign-in, how should the app remember and safely restore the page the user wanted?

level: seniorimportance: should knowfreq 55%

basics

~20 s

Capture the intended internal target when the guard redirects, carry it on the sign-in URL or the history entry's state, and treat it as untrusted: accept only a path on this origin, else a default.

open as a page

A lazily loaded route's bundle request 404s for a user whose tab has been open since before a deploy. What happened, and how should the app recover?

level: seniorimportance: should knowfreq 54%

basics

~20 s

The open document carries the old build's bundle filenames, and the deploy removed those files, so the loader's request misses. Recover at a route-level failure path: retry once or twice, then reload the document once, guarded so it cannot loop.

open as a page

Why do routers treat a navigation as a cancelable pending transition instead of swapping the screen immediately?

level: seniorimportance: should knowfreq 48%

basics

~20 s

Because the next screen is rarely ready when the address changes. A pending transition keeps the current screen visible and interactive, and can be abandoned when a second navigation supersedes it, so a slow first one cannot commit late.

open as a page

After a client-side router commits a navigation, how does it decide the new screen's scroll position, focus and title?

level: seniorimportance: should knowfreq 46%

basics

~20 s

A client-side commit resets nothing by itself, so the router needs a policy: top for a new destination, the saved offset for that history entry on a traversal, unchanged for a refinement, focus and title per route.

open as a page

A filter panel keeps its own copy of the filters and also writes them into the address; what goes wrong?

level: seniorimportance: should knowfreq 48%

basics

~20 s

Two copies of one value drift apart. Back and Forward change the address while the panel keeps its stale copy, and code that syncs both directions can loop. Make the address authoritative and derive the displayed values from it.

open as a page

showing 1–30 of 35