Next.js MCQs multiple-choice questions with answers & explanations
All 20 Next.js quiz questions on one page. Pick an answer in your head, then open Show answer to check it and read why. Want a score and a timer? Take them as a quiz instead.
Official reference: Next.js docs
- 1.mid
In Next.js 15, how does
next buildclassify this page, which uses no other request APIs?// app/prices/page.tsx export default async function Page() { const res = await fetch('https://api.example.com/prices'); const prices = await res.json(); return <p>{prices.length} prices</p>; }- A
○Static: prerendered at build - B
ƒDynamic: rendered per request - C
●SSG with generated params - DBuild error: fetch needs a cache option
Show answer
Answer: A (
○Static: prerendered at build)A plain
fetchis not stored in the Data Cache in Next.js 15, but it does not opt the route into dynamic rendering either. The fetch runs once at build time and its result is frozen into the prerendered page until the route is revalidated. Usecache: 'no-store',connection()or another request API to make it dynamic. - A
- 2.easy
Which of these, used inside a page Server Component, makes the route dynamically rendered?
- A
await cookies() - B
new Date().toISOString()in the JSX - CImporting a Client Component
- D
export const revalidate = 60
Show answer
Answer: A (
await cookies())cookies()reads data that only exists per request, so Next renders the route on demand (ƒ). Callingnew Date()does not opt out: the timestamp is simply captured at build time.revalidate = 60keeps the route static and adds background regeneration (ISR). - A
- 3.hard
Components
AandBboth render on the same page. How many times does the backend receive a request per page view?async function getTime() { const res = await fetch('https://api.example.com/time', { cache: 'no-store' }); return (await res.json()).now; } async function A() { return <p>a {await getTime()}</p>; } async function B() { return <p>b {await getTime()}</p>; } export default function Page() { return <><A /><B /></>; }- AOnce
- BTwice
- CZero: the page is static
- DOnce per build, then never again
Show answer
Answer: A (Once)
Next.js memoizes
GETfetches with the same URL and options for the duration of one server render, even withno-store. Both components get the same value from one request.no-storeonly means nothing is kept across requests, so the next page view fetches again. - 4.mid
Clickeris a'use client'component. What happens when this Server Component renders?import { Clicker } from './Clicker'; export default function Page() { return <Clicker onClick={() => console.log('clicked')} />; }- AWorks: the handler is sent to the browser
- BRender error: event handlers cannot be passed to Client Component props
- CThe handler runs on the server when clicked
- DThe prop is silently dropped
Show answer
Answer: B (Render error: event handlers cannot be passed to Client Component props)
Props that cross into a Client Component must be serializable, and an ordinary function is not. Next reports that event handlers cannot be passed to Client Component props. Define the handler inside the Client Component, or pass a Server Action, which is the one kind of function allowed across the boundary.
- 5.easy
You add
app/dashboard/error.tsxwithout a'use client'directive. What happens?- AIt works as a server error page
- BThe build fails: error.tsx must be a Client Component
- CIt is ignored and the root error page is used
- DIt only catches errors in production
Show answer
Answer: B (The build fails: error.tsx must be a Client Component)
error.tsxbecomes a React error boundary, and error boundaries rely on client-side lifecycle, so Next fails the build and asks for the directive. It also needs to be a Client Component to callreset()and retry rendering in the browser. - 6.mid
app/dashboard/layout.tsxthrows during render. Bothapp/error.tsxandapp/dashboard/error.tsxexist. Which one renders?- A
app/dashboard/error.tsx - B
app/error.tsx - C
app/global-error.tsxonly - DNeither: layouts cannot throw
Show answer
Answer: B (
app/error.tsx)A segment's
error.tsxwraps that segment's page and children, but sits inside itslayout.tsx. An error in the dashboard layout therefore bubbles to the parent boundary,app/error.tsx. Errors in the root layout needapp/global-error.tsx. - A
- 7.hard
The form is submitted. What does the user see, and what is logged on the server?
async function save() { 'use server'; try { await db.save(); redirect('/done'); } catch (e) { console.log('caught', (e as Error).message); } }- ARedirect to
/done; nothing logged - BNo redirect; logs
caught NEXT_REDIRECT - CRedirect to
/done; logscaught NEXT_REDIRECT - DA 500 error page
Show answer
Answer: B (No redirect; logs
caught NEXT_REDIRECT)redirect()works by throwing a special error with the messageNEXT_REDIRECT, which Next intercepts. Thecatchswallows it, so the redirect never happens. Callredirect()after thetry/catch, or rethrow withunstable_rethrow(e)fromnext/navigation. - ARedirect to
- 8.mid
A static page renders a Client Component that calls
useSearchParams(), with noSuspenseboundary around it. What doesnext builddo?- ABuilds fine; params are read on the client
- BFails: useSearchParams() should be wrapped in a suspense boundary
- CMarks the page as dynamic (
ƒ) - DPrerenders it with an empty query string and warns
Show answer
Answer: B (Fails: useSearchParams() should be wrapped in a suspense boundary)
Search params are unknown at build time, so the component must bail out to client rendering. Without a
Suspenseboundary the whole page would bail out, and Next fails the prerender with a missing-suspense error. Wrap the component inSuspenseso the rest of the page stays static. - 9.mid
In Next.js 15, what happens when a Server Component page contains this line?
const Chart = dynamic(() => import('./Chart'), { ssr: false });- AChart loads only in the browser
- BBuild error: ssr: false is not allowed in Server Components
- CThe option is ignored and Chart is server-rendered
- DChart is never rendered
Show answer
Answer: B (Build error: ssr: false is not allowed in Server Components)
Server Components never run in the browser, so "skip the server" has no meaning there, and Next.js 15 reports an error. Move the
dynamic(..., { ssr: false })call into a small Client Component and render that from the page. - 10.easy
How is this Route Handler rendered by default in Next.js 15?
// app/api/time/route.ts export async function GET() { return Response.json({ now: Date.now() }); }- AStatic: evaluated once at build
- BDynamic: runs on every request
- CCached for 60 seconds
- DCached until the next deployment
Show answer
Answer: B (Dynamic: runs on every request)
Next.js 15 made
GETRoute Handlers dynamic by default; in Next.js 14 this handler would have been prerendered at build time. Addexport const dynamic = 'force-static'if you want a static response. - 11.mid
A page has
export const revalidate = 60. The cached copy was generated 90 seconds ago. What does the next visitor get?- AThe stale cached page, while a fresh one is generated in the background
- BThey wait while the page is regenerated
- CA 503 until regeneration finishes
- DThe page as of the last deployment, forever
Show answer
Answer: A (The stale cached page, while a fresh one is generated in the background)
Time-based revalidation is stale-while-revalidate. The first request after the window still gets the cached page and triggers a background regeneration; later visitors get the new version once it succeeds. If regeneration fails, the last good page keeps being served.
- 12.mid
You change
NEXT_PUBLIC_API_URLin the hosting environment and restartnext startwithout rebuilding. What URL does client-side code use?- AThe new value
- BThe value from build time
- C
undefined - DWhichever value the server reads first
Show answer
Answer: B (The value from build time)
NEXT_PUBLIC_variables are inlined into the JavaScript bundle as literal strings when you runnext build. Restarting the server does not change already-built files, so the browser keeps the old value until you rebuild. - 13.easy
A
'use client'component rendersprocess.env.DATABASE_URL. What does the browser show?- AThe database URL
- BNothing: the value is
undefined - CA build error
- DThe string
process.env.DATABASE_URL
Show answer
Answer: B (Nothing: the value is
undefined)Only variables prefixed with
NEXT_PUBLIC_are inlined into client bundles. Others stay server-only, so in the browser the expression evaluates toundefined. That is a safety feature: secrets do not leak by accident. - 14.mid
In Next.js 15, what happens when a page reads
params.idwithout awaitingparams?export default function Page({ params }: any) { return <p>id {params.id}</p>; }- AIt renders
id undefined - BIt works, but development logs that params should be awaited
- CBuild error
- DTypeError: cannot read properties of a Promise
Show answer
Answer: B (It works, but development logs that params should be awaited)
Next.js 15 made
paramsa Promise but keeps temporary synchronous access for migration. The page renders the id, andnext devlogs thatparamsshould be awaited before using its properties. Writeconst { id } = await paramsin an async page. - AIt renders
- 15.mid
With this middleware config, which request does middleware not run for?
export const config = { matcher: ['/dashboard/:path*'] };- A
/dashboard - B
/dashboard/settings - C
/dashboard/a/b - D
/dashboards
Show answer
Answer: D (
/dashboards):path*matches zero or more segments after/dashboard/, so/dashboarditself and any depth below it match./dashboardsis a different first segment and is skipped. A matcher that misses a route is a classic way to leave a page unprotected. - A
- 16.mid
What is the response for
/posts/c?// app/posts/[slug]/page.tsx export const dynamicParams = false; export async function generateStaticParams() { return [{ slug: 'a' }, { slug: 'b' }]; }- A200, rendered on demand and cached
- B404
- C500
- DA redirect to
/posts/a
Show answer
Answer: B (404)
With
dynamicParams = false, only the params returned bygenerateStaticParamsexist; anything else is a 404, likefallback: falsein the Pages Router. With the defaulttrue,/posts/cwould be rendered on its first request. - 17.hard
The delete button is only rendered for admins. Can a non-admin trigger
deletePost?async function deletePost(formData: FormData) { 'use server'; await db.post.delete({ where: { id: formData.get('id') as string } }); }- ANo: the action ID is only sent to admins
- BYes: an action is a POST endpoint anyone can call once they have its ID
- CNo: middleware blocks direct action calls
- DOnly if they disable JavaScript
Show answer
Answer: B (Yes: an action is a POST endpoint anyone can call once they have its ID)
A Server Action is invoked with a plain
POSTthat carries its action ID, and any client can send that request. Hiding UI is not access control. Check the session and the user's role inside the action before touching the database. - 18.easy
A component in
app/callsuseStatebut the file has no directive. What happens?- AIt works; hooks run on the server
- BCompile error: the hook only works in a Client Component
- CState resets on every render, without errors
- DNext adds
use clientautomatically
Show answer
Answer: B (Compile error: the hook only works in a Client Component)
Files in
app/are Server Components by default, and Server Components cannot hold state. Next fails with an error saying the hook only works in a Client Component. Add'use client'to that file, ideally a small interactive leaf rather than the whole page. - 19.mid
This Client Component is rendered on a dynamic page. What happens in a production build?
'use client'; export function Clock() { return <p>{Date.now()}</p>; }- ANothing unusual: the server value is kept
- BReact reports a hydration mismatch (minified error #418) and re-renders the tree on the client
- CThe build fails
- DThe component renders only on the client
Show answer
Answer: B (React reports a hydration mismatch (minified error #418) and re-renders the tree on the client)
Client Components are server-rendered first, then hydrated. The server and the browser call
Date.now()at different moments, so the text differs and React 19 throws a hydration error (#418 in production) and regenerates that tree on the client. Render a stable value first and update it inuseEffect. - 20.hard
What does
router.refresh()fromnext/navigationdo?- AReloads the browser tab and resets all state
- BRe-requests the current route from the server and merges it, keeping client state
- CPurges the server Data Cache for the route
- DClears every cache layer, including ISR pages
Show answer
Answer: B (Re-requests the current route from the server and merges it, keeping client state)
router.refresh()clears the client Router Cache for the current route and asks the server for a fresh RSC payload, merging it without losinguseStateor scroll position. It does not invalidate the Data Cache or Full Route Cache: if the server data is cached, you get the same cached result. UserevalidatePathorrevalidateTagfor that.
No questions match these filters. Try a different subtopic or clear the filters.