skip to content

Routing & Data-fetching

The layer between your components and the outside world: client-side routers, HTTP and GraphQL clients, caching libraries, and form and validation utilities. Front-end interviews spend a lot of time here because it is where most real application complexity actually lives.

on this pageshow

explore

questions

163 · 11 sections

In React Router 7's data mode, what do a route's loader and action functions receive, and how does a component read what each returned?

level: juniorimportance: must knowfreq 72%
basics
~20 s

In React Router 7, loader and action are route-object functions that each receive a Fetch Request and the matched params. The loader runs before the route renders and is read with useLoaderData; the action handles non-GET submissions and is read with useActionData.

open as a page

In React Router v7, how do you configure /projects/:projectId/tasks/:taskId so every screen renders inside one shared dashboard shell?

level: juniorimportance: must knowfreq 68%
basics
~20 s

Nest the routes: a shell route whose element renders the sidebar and an <Outlet />, with projects/:projectId and then tasks/:taskId as descendants in children. Child paths are relative and each parent renders its matched child where it places <Outlet />.

open as a page

In React Router v7, what type are the values useParams returns, and what must you do before using :productId as a number?

level: juniorimportance: must knowfreq 64%
basics
~20 s

useParams values are strings or undefined, decoded from the URL and never coerced. A :productId segment matches any text, so parse it, check the result, and render a not-found or error state when it is missing or invalid.

open as a page

Compared with React Router's useSearchParams, how does TanStack Router's validateSearch keep a product list's page and filter search params typed and refactor-safe?

level: middleimportance: must knowfreq 45%
basics
~20 s

React Router's useSearchParams yields URLSearchParams strings that each reader parses. TanStack Router parses the query JSON-first and runs the route's validateSearch once, so Route.useSearch() is typed and every Link or navigate writing search is checked against that schema.

open as a page

In TanStack Router, what is the difference between file-based routes generated by the bundler plugin and code-based routes built with createRoute?

level: juniorimportance: should knowfreq 38%
basics
~20 s

Both produce the same typed route tree. File-based routing lets the TanStack Router bundler plugin generate routeTree.gen.ts from files that call createFileRoute; code-based routing builds the tree by hand with createRootRoute, createRoute({ getParentRoute, path }) and addChildren.

open as a page

In TanStack Router, how do beforeLoad and router context let an _authenticated layout route gate its children using auth state that lives in a React hook?

level: middleimportance: should knowfreq 40%
basics
~20 s

Declare the context type with createRootRouteWithContext, pass the hook's value through <RouterProvider context={{ auth }}>, and read context.auth in the layout's beforeLoad, throwing redirect() when signed out. beforeLoad runs parent-first before loaders; call router.invalidate() when auth changes.

open as a page

A TanStack Router /products loader reads the page from location.search, and changing ?page=2 keeps showing page 1's data; why, and how do loaderDeps and staleTime fix it?

level: seniorimportance: should knowfreq 32%
basics
~20 s

TanStack Router caches loader results per route match, keyed by route, path params and loaderDeps — not the search string. A search-only change keeps the same match, so the loader is not re-run. Declaring loaderDeps for page gives each page its own entry.

open as a page

In Vue Router 5 file-based routing, how do src/pages files become routes, and what do index.vue, [slug].vue and [...path].vue generate?

level: juniorimportance: must knowfreq 40%
basics
~10 s

The vue-router/vite plugin scans src/pages and generates the route records, which you import from vue-router/auto-routes. index.vue maps to its folder's path, [slug].vue to a :slug param, and [...path].vue to the catch-all /:path(.*).

open as a page

In Vue Router 5, how do you write a `router.beforeEach` guard that uses `to.meta.requiresAuth` to send signed-out HR-portal users to `/login` with their destination?

level: juniorimportance: must knowfreq 72%
basics
~20 s

Register router.beforeEach((to) => …) and, when to.meta.requiresAuth is set and nobody is signed in, return { name: 'login', query: { redirect: to.fullPath } }. Returning nothing lets every other navigation through; keep the login route itself unprotected.

open as a page

In Vue Router 5, how do you lazy-load a dashboard route's component, and what breaks if you write `component: import('./Billing.vue')` without the arrow function?

level: juniorimportance: must knowfreq 65%
basics
~20 s

Give the route a loader, component: () => import('./Billing.vue'); the router calls it on first entry, waits for it and caches the result. Without the arrow the import runs at startup, and development warns that production will break.

open as a page

In Vue Router 5, how does a route record with path '/products/:id' match URLs, and how does a script setup component read the id?

level: juniorimportance: must knowfreq 66%
basics
~10 s

The :id segment matches exactly one non-empty path segment, so /products/42 matches and /products/42/reviews does not; a component reads it as useRoute().params.id, a decoded string.

open as a page

In TanStack Query v5, how do you make a query for a user's projects wait until another query has returned that user's id?

level: juniorimportance: must knowfreq 66%
basics
~20 s

Give the projects query enabled: !!userId and put userId in its query key. While disabled it sits in status pending with fetchStatus idle, and it fetches on its own as soon as the id arrives.

open as a page

In TanStack Query v5, after a mutation that creates a todo succeeds, how do you make the todo lists on screen show it?

level: juniorimportance: must knowfreq 70%
basics
~10 s

In the mutation's onSuccess, call queryClient.invalidateQueries({ queryKey: ['todos'] }). Every query whose key starts with 'todos' is marked stale; those currently rendered refetch in the background at once, the rest refetch when next mounted.

open as a page

In TanStack Query v5, what is the difference between the mutate and mutateAsync functions that useMutation returns?

level: juniorimportance: must knowfreq 68%
basics
~20 s

mutate starts the mutation and returns nothing; errors are caught internally and surface through callbacks and the hook's error state. mutateAsync returns a promise that resolves with the data or rejects with the error, so you must catch it yourself.

open as a page

In TanStack Query v5, how does useInfiniteQuery decide which page to fetch next, and how does it know there are no more pages?

level: juniorimportance: must knowfreq 62%
basics
~10 s

useInfiniteQuery fetches the first page with initialPageParam, then asks getNextPageParam(lastPage, allPages, lastPageParam, allPageParams) for each next param. Returning undefined or null sets hasNextPage to false. Pages accumulate in data.pages and data.pageParams.

open as a page

In TanStack Query v5, a todo list keyed ['todos'] has a queryFn reading a status filter; why does a filter change show the wrong list?

level: juniorimportance: must knowfreq 70%
basics
~20 s

The key is the cache identity, and ['todos'] never changes, so every filter shares one entry and a filter change starts no fetch. Put every variable the queryFn uses into the key, such as ['todos', 'list', { status }].

open as a page

With SWR, a profile header and a settings page both call useSWR('/api/user', fetcher); how many requests go out, and how do they share data?

level: juniorimportance: must knowfreq 48%
basics
~20 s

Both hooks share the one cache entry named by '/api/user'. Mounted together they send one request, because SWR dedupes revalidations of a key within dedupingInterval (2000 ms). A later mount shows the cached user at once and revalidates in the background.

open as a page

In SWR 2, how do null, function and array keys change what useSWR fetches, and what does the fetcher receive for an array key?

level: middleimportance: should knowfreq 40%
basics
~20 s

A null or falsy key fetches nothing. A function key is called, and fetches nothing if it throws or returns a falsy value. Array and object keys are hashed stably and reach the fetcher as one argument, not spread.

open as a page

In SWR, how do you use mutate to show a user's new display name in the header immediately and roll it back if saving fails?

level: middleimportance: should knowfreq 42%
basics
~20 s

Call mutate for '/api/user' with the save promise and optimisticData set to the edited user. The header updates at once; if the promise rejects, rollbackOnError (default true) restores the previous data, and revalidate (default true) refetches afterwards.

open as a page

Compared with TanStack Query, what does SWR deliberately leave out of its cache model, and how does that change the code you write?

level: middleimportance: should knowfreq 38%
basics
~20 s

SWR has no freshness setting like staleTime, no automatic eviction like gcTime, and no AbortSignal for the fetcher. You turn revalidation off per hook where it is not needed, clear the cache yourself, and handle cancellation in your own code.

open as a page

After one user logs out and another logs in, an SWR app briefly shows the previous user's profile and orders; why, and how do you clear SWR's cache correctly?

level: seniorimportance: should knowfreq 30%
basics
~20 s

SWR's cache outlives the session, and '/api/user' is the same key for both users, so the new user first sees the old cached data. On logout call unload({ revalidate: false }) (SWR 2.5+), or give each session its own cache provider.

open as a page

In Apollo Client 4, why does ProductCard declare its own fragment, and how does that fragment reach the product listing page's query?

level: juniorimportance: must knowfreq 45%
basics
~10 s

ProductCard declares a fragment so the fields it renders live beside the code that renders them. The listing query spreads ...ProductCardFragment and interpolates its definition, so one request fetches every card's fields.

open as a page

In Apollo Client 4, what is a reactive variable created with makeVar, and how would you use one for a shop's cart drawer open flag?

level: juniorimportance: must knowfreq 36%
basics
~20 s

A reactive variable is the function makeVar(initialValue) returns: call it with no argument to read, with one argument to write. It lives outside the cache, and components that read it through useReactiveVar re-render when it changes.

open as a page

In Apollo Client 4, how does InMemoryCache store an author shown on fifty feed posts, and what breaks if the query omits the author's id?

level: juniorimportance: must knowfreq 58%
basics
~20 s

InMemoryCache stores each object with __typename and id once, under a cache ID such as Author:42, and every post references it. Without id in the feed query, each post embeds its own author copy and renames stop propagating.

open as a page

In Apollo Client 4, what does useQuery return for an issue list while loading, on error and on success, and how do you render each?

level: juniorimportance: must knowfreq 62%
basics
~20 s

Apollo Client 4's useQuery returns loading, error, data and dataState, which can overlap: cached rows arrive with loading true, and a failed refetch keeps rows beside error. Render data when present, else the error or a spinner.

open as a page

In Apollo Client 4, what does the useSubscription hook give a notification badge, and when does the badge re-render?

level: juniorimportance: must knowfreq 38%
basics
~20 s

useSubscription, imported from @apollo/client/react, returns loading, data, error and restart. loading stays true until the first event arrives; after that, data holds only the latest event, and the component re-renders as each pushed event lands.

open as a page

What does the relay-compiler do with the graphql-tagged queries and fragments in a Relay app, and why must it run before the app works?

level: juniorimportance: must knowfreq 38%
basics
~20 s

The relay-compiler validates every graphql tag against the schema ahead of time and writes a generated artifact per query or fragment: runtime metadata, query text and types. A Babel plugin swaps each tag for its artifact, so uncompiled tags throw.

open as a page

In Relay, why can't a parent component read the fields its child's useFragment fragment selects, even though they arrive in the same response?

level: middleimportance: must knowfreq 36%
basics
~20 s

Relay's data masking: useFragment returns only the fields its own fragment selected. A spread child fragment reaches the parent as an opaque fragment reference, which the child passes to useFragment to read its fields from the store.

open as a page

In Relay, how do useLazyLoadQuery and usePreloadedQuery with useQueryLoader differ in when an article page's query starts fetching?

level: middleimportance: should knowfreq 30%
basics
~20 s

useLazyLoadQuery starts fetching only when its component renders, so code loading and parent renders delay it and nested lazy queries waterfall. With useQueryLoader, an event handler or route transition calls loadQuery first, and usePreloadedQuery later reads that reference, suspending until it resolves.

open as a page

With Relay's usePaginationFragment, what must a news article's comment-thread fragment declare, and how does loadNext add the next page?

level: middleimportance: should knowfreq 27%
basics
~20 s

The fragment needs @argumentDefinitions for count and cursor, @refetchable(queryName) so the compiler generates a pagination query, and @connection(key) on the comments field. loadNext(n) sends that query from the current end cursor, and Relay appends the new edges to the stored connection.

open as a page

In Relay, a news article's like button and add-comment form both use useMutation; how do the like count and the comment thread update, instantly and after the server replies?

level: seniorimportance: should knowfreq 24%
basics
~20 s

Relay merges payload objects into stored records by id, so a like payload selecting likeCount updates every reader; an optimisticResponse shows it instantly and is rolled back on reply. A new comment is inserted with @prependEdge and the thread's connection id.

open as a page

In urql 5 for React, how do you create and provide a Client, and what does exchanges: [cacheExchange, fetchExchange] do?

level: juniorimportance: must knowfreq 38%
basics
~20 s

An urql Client is built with createClient({ url, exchanges }) and handed to components through Provider. The required exchanges array is a pipeline: cacheExchange answers from the document cache, fetchExchange sends everything else over HTTP.

open as a page

In urql, what do the four requestPolicy values do, and when would a storefront screen pick cache-and-network over the default?

level: middleimportance: must knowfreq 34%
basics
~10 s

urql's requestPolicy is cache-first by default, returning a cached result or fetching once. cache-and-network returns the cached result marked stale and refetches, network-only always fetches, and cache-only never sends a request.

open as a page

In urql's default document cache, why does an empty cart keep showing no items after an addToCart mutation succeeds, and how do you fix it?

level: middleimportance: should knowfreq 28%
basics
~20 s

urql's document cache invalidates cached queries whose results contained a __typename that the mutation result contains. An empty cart's lines list carries no CartLine typename, so nothing links it to addToCart; additionalTypenames adds that link.

open as a page

When an urql storefront moves from the document cache to Graphcache, what do its keys, updates and optimistic options configure, and what breaks without them?

level: seniorimportance: should knowfreq 22%
basics
~10 s

Graphcache's keys say how to identify entities without an id, updates.Mutation holds updaters for list and link changes a mutation result cannot express, and optimistic returns a temporary result applied until the server answers.

open as a page

For a React storefront team choosing between urql and Apollo Client 4, when is urql the better fit, and what does the team give up?

level: principalimportance: should knowfreq 20%
basics
~20 s

urql fits when a team wants a small, exchange-based client that starts with a simple document cache and adds Graphcache only when shared entities demand it. The team gives up built-in local state and Apollo's freedom to write to the cache anywhere.

open as a page

In React Hook Form, what does register('email', { required: true }) give an input, and what does handleSubmit do before calling your callback?

level: juniorimportance: must knowfreq 75%
basics
~20 s

In React Hook Form, register returns name, ref, onChange and onBlur to spread onto a native input. handleSubmit prevents the default submit, validates every field, then calls onValid(data) only when no errors remain, otherwise onInvalid(errors).

open as a page

In a React Hook Form signup form, how do you connect a controlled date-picker component that takes value and onChange but exposes no native input?

level: middleimportance: must knowfreq 60%
basics
~10 s

Wrap the date-picker in React Hook Form's Controller (or call useController) with name, control and rules. Its render prop supplies field.value, field.onChange, field.onBlur and field.ref, which you map onto the picker's own props.

open as a page

Why does typing into a React Hook Form input usually not re-render the form component, when the same keystroke in a Formik form does?

level: middleimportance: must knowfreq 62%
basics
~20 s

React Hook Form leaves registered values in the DOM and its own store, and re-renders only for formState you read. Formik keeps values in the form owner's state, so each keystroke re-renders that component and its children.

open as a page

In React Hook Form, what do the useForm options mode and reValidateMode control, and what are their defaults?

level: middleimportance: should knowfreq 50%
basics
~20 s

In React Hook Form, mode sets when fields validate before the first submit (default 'onSubmit'); reValidateMode sets when they validate after a submit (default 'onChange'). By default nothing validates while typing until the user has submitted once.

open as a page

A React Hook Form signup form renders useFieldArray phone rows with key={index}, and after removing a middle row, row-level state sticks to the wrong numbers — why, and what is the fix?

level: seniorimportance: should knowfreq 45%
basics
~20 s

React keeps component state and DOM nodes by key, so with index keys a removal makes the surviving rows inherit the removed row's state. useFieldArray gives every row a stable field.id; use key={field.id}, as the documentation requires.

open as a page

In Formik 2, what do <Formik>, <Form>, <Field> and <ErrorMessage> each wire up, and when would you call useFormik directly instead?

level: juniorimportance: must knowfreq 45%
basics
~20 s

In Formik 2, <Formik> owns the form state and provides it through context; <Form> wires submit and reset; <Field> binds an input to values, handleChange and handleBlur; <ErrorMessage> shows a touched field's error. useFormik returns the same state without context.

open as a page

In Formik 2, a field's error already exists in errors while the user types, yet no message shows until they leave the field — why?

level: middleimportance: should knowfreq 40%
basics
~20 s

Formik 2 validates the whole form on every change and blur by default, so errors fills in while the user types. touched.field is set only by blur or submit, and the usual display gate — including ErrorMessage — needs both.

open as a page

A Formik 2 form's submit button, disabled by isSubmitting, stays disabled forever after the first submit — what in onSubmit causes that?

level: middleimportance: should knowfreq 38%
basics
~10 s

Formik 2 resets isSubmitting only when onSubmit returns a promise, once it settles. A synchronous onSubmit, or one that starts a request without returning it, leaves isSubmitting true until you call setSubmitting(false).

open as a page

In Formik 2, how do you build a reusable custom input with useField, and what do the three values it returns hold?

level: middleimportance: should knowfreq 35%
basics
~20 s

In Formik 2, useField(name) returns [field, meta, helpers]: field holds name, value, onChange and onBlur to spread onto an input; meta holds value, error, touched and initial values; helpers holds setValue, setTouched and setError for non-event widgets.

open as a page

A Formik 2 edit-profile form renders before the user record loads and stays empty after it arrives — how do you fix it, and what does enableReinitialize risk?

level: seniorimportance: should knowfreq 35%
basics
~20 s

Formik 2 reads initialValues once, at mount. enableReinitialize resets the form whenever initialValues changes by deep equality, which discards unsaved edits if the loaded data changes again; rendering after load or keying by user id avoids that.

open as a page

With VeeValidate 4's useForm and defineField, how do you bind a sign-up form's email input and show its validation error?

level: juniorimportance: must knowfreq 34%
basics
~10 s

Call useForm with a schema, then const [email, emailAttrs] = defineField('email'). Bind the input with v-model="email" and v-bind="emailAttrs", and render errors.email, the field's first error message.

open as a page

In VeeValidate 4 with a toTypedSchema Zod schema, why are form values typed partial while handleSubmit's callback gets required fields, and when does the callback not run?

level: middleimportance: should knowfreq 27%
basics
~20 s

toTypedSchema tells VeeValidate the schema's input type, a deep partial of what users are filling in, and its output type, what a valid parse returns. handleSubmit validates everything first and only calls your callback, with the output, when the form is valid.

open as a page

In a VeeValidate 4 sign-up form, how do you render a repeatable phone list with useFieldArray, and why key rows by field.key but name them by index?

level: seniorimportance: should knowfreq 19%
basics
~20 s

useFieldArray('phones') returns read-only fields plus helpers such as push and remove. Key the v-for on field.key, a stable generated id, but name each input phones[idx], because the form stores an array and paths are positional.

open as a page

In VeeValidate 4, why does a sign-up email field bound with defineField show an error on the first keystroke, and how do you make it validate on blur instead?

level: seniorimportance: should knowfreq 23%
basics
~20 s

defineField's model validates on every update because validateOnModelUpdate defaults to true, and v-model updates on each keystroke. Pass defineField('email', { validateOnModelUpdate: false }) and the field validates on blur and change instead, which stay on by default.

open as a page

In a VeeValidate 4 sign-up form validated by one Zod schema, why does an async username-availability refine fire on keystrokes in other fields, and how do you contain it?

level: seniorimportance: nice to knowfreq 16%
basics
~20 s

With a form-level schema, validating any field parses the whole schema, so an async username refine runs whenever email or password validate. Cache the lookup per username, make the field lazy, and show meta.pending while it runs.

open as a page