In a client-side router, what is a route guard and what verdicts can it return for a pending navigation?
answer
- stands in the corridor, not the room
- matched, then guarded, then rendered
- three verdicts, not two
- usually asynchronous, awaits the session
- hiding a route enforces nothing
basics
~20 sA 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 sA 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
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.
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.
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.
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