Lesson 6 of 81
Two files with almost the same job — wrap children with shared UI — that behave in opposite ways on navigation. Picking the wrong one either silently loses state you needed to keep, or silently keeps state you needed to reset.
10 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 3
A sidebar's expanded/collapsed state is stored in local component state inside `app/dashboard/layout.tsx`. A user navigates from `/dashboard/overview` to `/dashboard/settings`. Does the sidebar's expanded/collapsed state survive?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
Both layout.tsx and template.tsx wrap a segment's content in shared UI, and both accept a children prop. The difference is entirely about what happens to that wrapper on navigation:
layout.tsx — persists. When you navigate between sibling pages under the same layout, the layout instance is not re-rendered or remounted: any local state inside it, any running effects, any DOM inside it, all survive untouched. This is why a layout is the right place for things like a sidebar's scroll position or an open/closed nav state.template.tsx — remounts. Every navigation gives it a fresh key, so React treats it as a brand-new instance: local state resets, useEffect cleanup runs and effects re-fire, and the DOM inside it is fully recreated. In the component hierarchy, a template sits between a layout and the page — it wraps page.tsx (and error.tsx, loading.tsx, not-found.tsx) but does not wrap the layout.tsx at that same segment level.Both default to Server Components, and both can hold Client Components inside them — the persist-vs-remount distinction is about the React tree identity, not about server/client rendering.
// app/blog/template.tsx — remounts on every navigation within /blog
"use client";
import { motion } from "framer-motion";
export default function BlogTemplate({ children }: { children: React.ReactNode }) {
return (
<motion.div initial={{ opacity: 0, y: 8 }} animate={{ opacity: 1, y: 0 }}>
{children}
</motion.div>
);
}
If this were layout.tsx instead, the entrance animation would only ever play once — on the first load of /blog — because a layout that isn't remounting has nothing to "enter" on subsequent navigations to /blog/first-post or /blog/second-post. As a template.tsx, it gets a fresh key on every one of those navigations, so the fade-and-slide-in genuinely replays each time a new post loads. The same reasoning applies to resetting a search input's local state between pages, or forcing an analytics useEffect to fire again on every route change instead of just once.
searchParams or the current pathname directly; they'd go stale. Read those in a Client Component using useSearchParams/usePathname instead, since those re-render on navigation.template.tsx and layout.tsx in the same folder aren't nested inside each other in a simple parent-child way — the layout wraps the template, and the template wraps everything below it, but the template never wraps its own sibling layout.template.tsx "just in case" costs real re-render and remount work on every navigation — reach for it specifically when you need the reset-on-navigate behavior (entrance animations, force-resetting form state, re-firing effects per route), not as a default alternative to layout.tsx.<html>/<body> included."A page's local state is resetting when a candidate expects it to persist across navigation, or vice versa" is a debugging scenario that maps directly onto whether someone actually understands the layout/template persistence distinction, versus having only ever used layout.tsx and never noticed template.tsx exists.