{"checkpoints":{"s-rf-1":[{"q":"<p>A teammate clones the Watchlist repository and runs <code dir=\"ltr\">npm run dev</code>. The terminal says <code dir=\"ltr\">vite: command not found</code>. What should they do?</p>","options":[{"text":"Install Vite globally with <code dir=\"ltr\">npm install -g vite</code>.","why":"A global install hides the real problem and can run a different Vite version than the project expects."},{"text":"Delete <code dir=\"ltr\">package-lock.json</code> and try again.","why":"The lockfile is what makes installs reproducible. Deleting it changes nothing about the missing folder."},{"text":"Run <code dir=\"ltr\">npm install</code> first, because <code dir=\"ltr\">node_modules</code> is not stored in Git.","why":"Correct. <code dir=\"ltr\">npm install</code> reads package.json and the lockfile and installs Vite locally, which is what <code dir=\"ltr\">npm run dev</code> uses."},{"text":"Rename <code dir=\"ltr\">index.html</code> so Vite can find it.","why":"Vite finds index.html at the project root already. The command itself is missing, not the entry file."}],"answer":2},{"q":"<p>Vite shows “Adjacent JSX elements must be wrapped in an enclosing tag” for this component. Which fix is correct?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"jsx\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">JSX</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">export</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> default</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> App</span><span style=\"color:#953800;--shiki-dark:#FFA657\">() </span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>Watchlist&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>3 to watch&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  );</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n","options":[{"text":"Wrap both elements in a fragment <code dir=\"ltr\">&lt;&gt;…&lt;/&gt;</code> or in a meaningful element such as <code dir=\"ltr\">&lt;header&gt;</code>.","why":"Correct. A component returns one root. A fragment groups siblings without adding a DOM node."},{"text":"Remove the parentheses around the JSX.","why":"The parentheses only protect the multi-line return. Without them the function returns nothing useful."},{"text":"Put a comma between the two elements.","why":"A comma would create a JavaScript comma expression that returns only the last element, which still is not what you want."},{"text":"Split the return into two <code dir=\"ltr\">return</code> statements.","why":"A function stops at its first <code dir=\"ltr\">return</code>, so the second element would never be rendered."}],"answer":0},{"q":"<p><code dir=\"ltr\">count</code> is 0 and <code dir=\"ltr\">watched</code> is <code dir=\"ltr\">true</code>. What text does <code dir=\"ltr\">&lt;p&gt;{count} {watched}&lt;/p&gt;</code> show?</p>","options":[{"text":"“0 true”","why":"React does not render booleans as text. <code dir=\"ltr\">true</code> produces nothing."},{"text":"Nothing at all, because both values are skipped.","why":"Booleans are skipped, but numbers are always rendered, including 0."},{"text":"An error, because booleans are not valid children.","why":"Booleans are valid children; they just render nothing, which is what makes <code dir=\"ltr\">&amp;&amp;</code> work."},{"text":"“0” (with a trailing space), because numbers render and booleans render nothing.","why":"Correct. 0 is a number and appears as text; <code dir=\"ltr\">true</code> is ignored."}],"answer":3},{"q":"<p><code dir=\"ltr\">src/components/MovieCard.jsx</code> contains <code dir=\"ltr\">export function MovieCard() { … }</code> and nothing else. Which import works in App.jsx?</p>","options":[{"text":"<code dir=\"ltr\">import MovieCard from &quot;./components/MovieCard.jsx&quot;;</code>","why":"Without braces you ask for the default export, and this file has none, so the value is undefined."},{"text":"<code dir=\"ltr\">import { MovieCard } from &quot;./components/MovieCard.jsx&quot;;</code>","why":"Correct. A named export is imported by name inside curly braces."},{"text":"<code dir=\"ltr\">import { MovieCard } from &quot;MovieCard&quot;;</code>","why":"A bare specifier like “MovieCard” is looked up in node_modules. Your own files need a relative path."},{"text":"<code dir=\"ltr\">import * from &quot;./components/MovieCard.jsx&quot;;</code>","why":"That is not valid syntax. A namespace import needs a name: <code dir=\"ltr\">import * as Cards from …</code>."}],"answer":1},{"q":"<p>A colleague removes <code dir=\"ltr\">&lt;StrictMode&gt;</code> from main.jsx because logs print twice in development. What is the best response?</p>","options":[{"text":"Agree, because StrictMode makes the production app twice as slow.","why":"StrictMode has no effect in production builds at all."},{"text":"Agree, because StrictMode is deprecated in React 19.","why":"StrictMode is current and recommended in React 19."},{"text":"Keep it: the double run only happens in development and exists to expose impure rendering and missing cleanups early.","why":"Correct. The extra logs are the cost of a check that catches real bugs before users do."},{"text":"Keep it, but wrap each component in its own StrictMode as well.","why":"One StrictMode at the root already covers the whole tree. Nesting more adds nothing."}],"answer":2}],"s-rf-2":[{"q":"<p><code dir=\"ltr\">&lt;MovieCard title=&quot;Arrival&quot; watched=&quot;false&quot; /&gt;</code> shows the “Watched” badge, and the component uses <code dir=\"ltr\">{watched &amp;&amp; &lt;Badge /&gt;}</code>. Why?</p>","options":[{"text":"Quotes pass the string “false”, and any non-empty string is truthy. Pass <code dir=\"ltr\">watched={false}</code> instead.","why":"Correct. Only strings can be passed in quotes; booleans, numbers and objects need braces."},{"text":"Boolean props must always be written as a bare attribute.","why":"A bare attribute means <code dir=\"ltr\">true</code>. To pass false you write <code dir=\"ltr\">watched={false}</code> or leave the prop out."},{"text":"<code dir=\"ltr\">&amp;&amp;</code> does not work with props.","why":"<code dir=\"ltr\">&amp;&amp;</code> works with any value. The problem is the type of the value that was passed."},{"text":"The default value in the component overrides the prop.","why":"Defaults only apply when the prop is undefined. Here the prop is the string “false”."}],"answer":0},{"q":"<p>The list renders, but the console warns “Each child in a list should have a unique key prop”. Where is the mistake?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"jsx\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">JSX</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> MovieItem</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">({ </span><span style=\"color:#953800;--shiki-dark:#FFA657\">movie</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }) {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">li</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> key</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">={</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">movie.id</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">movie.title</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">li</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{movies.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">map</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">((</span><span style=\"color:#953800;--shiki-dark:#FFA657\">movie</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=></span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">MovieItem</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> movie</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">={</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">movie</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> />)}</span></span></code></pre></div>\n","options":[{"text":"<code dir=\"ltr\">movie.id</code> is not unique enough; use the index.","why":"The ids are fine. The key is simply in the wrong place, and the index would make reordering bugs worse."},{"text":"The <code dir=\"ltr\">&lt;ul&gt;</code> around the list needs a key.","why":"The <code dir=\"ltr\">&lt;ul&gt;</code> is a single element. The items returned from <code dir=\"ltr\">map</code> are the siblings React must tell apart."},{"text":"Keys only work on HTML elements, not components.","why":"Keys work on components too; that is exactly where this one belongs."},{"text":"The key must be on <code dir=\"ltr\">&lt;MovieItem key={movie.id} … /&gt;</code> in the <code dir=\"ltr\">map</code>, not on the <code dir=\"ltr\">&lt;li&gt;</code> inside the component.","why":"Correct. React reads keys from the elements in the array, which here are the MovieItem elements."}],"answer":3},{"q":"<p>You are building a <code dir=\"ltr\">Dialog</code> with a title, any body content, and buttons that differ per use. Which API keeps Dialog simple and flexible?</p>","options":[{"text":"A <code dir=\"ltr\">buttons</code> prop with an array of label strings, and Dialog creates the buttons and their click handlers.","why":"Dialog would need to know every action in the app. The API grows with each new use."},{"text":"<code dir=\"ltr\">title</code> as a prop, the body as <code dir=\"ltr\">children</code>, and a <code dir=\"ltr\">footer</code> prop that takes JSX such as <code dir=\"ltr\">footer={&lt;button onClick={close}&gt;Close&lt;/button&gt;}</code>.","why":"Correct. Dialog owns the frame and positions the slots; callers decide what goes in them."},{"text":"One Dialog component per use, copied and edited each time.","why":"Copies drift apart and every style fix must be repeated in each one."},{"text":"Pass the whole dialog markup as an HTML string.","why":"HTML strings skip React components and escaping, and are unsafe with any user data."}],"answer":1},{"q":"<p>A movie has <code dir=\"ltr\">genres: [&quot;drama&quot;, &quot;sci-fi&quot;]</code>, and genres never repeat within a movie. What is a good key when rendering them?</p>","options":[{"text":"<code dir=\"ltr\">Math.random()</code>, so keys are always unique.","why":"A new key every render forces React to recreate each element on every render."},{"text":"The index, because the list is short.","why":"Short lists can still reorder. When a stable unique value exists, prefer it."},{"text":"The genre string itself, because it is unique within the list and stable.","why":"Correct. Keys only need to be unique among siblings and stable over time, and the string is both."},{"text":"No key, because strings do not need keys.","why":"Every element returned from <code dir=\"ltr\">map</code> needs a key, whatever data it came from."}],"answer":2},{"q":"<p>A <code dir=\"ltr\">MovieTitle</code> component should display its <code dir=\"ltr\">title</code> prop in uppercase. Which version is correct?</p>","options":[{"text":"<code dir=\"ltr\">const upper = title.toUpperCase(); return &lt;h2&gt;{upper}&lt;/h2&gt;;</code>","why":"Correct. Derive a new value from the prop during render and leave the prop itself alone."},{"text":"<code dir=\"ltr\">props.title = props.title.toUpperCase(); return &lt;h2&gt;{props.title}&lt;/h2&gt;;</code>","why":"That writes to props, which belong to the parent. React freezes props in development, so it throws."},{"text":"<code dir=\"ltr\">const [upper] = useState(title.toUpperCase());</code> then render <code dir=\"ltr\">upper</code>.","why":"State only reads its initial value once, so the heading would ignore later title changes."},{"text":"<code dir=\"ltr\">useEffect(() =&gt; setUpper(title.toUpperCase()), [title]);</code> then render <code dir=\"ltr\">upper</code>.","why":"An Effect plus state for a derived value adds an extra render with stale text. Compute it during render."}],"answer":0}],"s-rf-3":[{"q":"<p>A “+1 later” button runs <code dir=\"ltr\">setTimeout(() =&gt; setCount(count + 1), 1000)</code>. You click it three times within a second. <code dir=\"ltr\">count</code> was 0. What is it after the timers fire?</p>","options":[{"text":"3, because three timers ran.","why":"Each timer closed over the <code dir=\"ltr\">count</code> from the render it was created in, which was 0 each time."},{"text":"0, because state cannot be set from a timer.","why":"Setting state from a timer is fine; it does update."},{"text":"An error about setting state outside an event handler.","why":"React allows state updates from timers, promises and handlers alike."},{"text":"1, because every timer computed 0 + 1. Use <code dir=\"ltr\">setCount((c) =&gt; c + 1)</code> to get 3.","why":"Correct. The updater receives the latest value instead of a stale snapshot."}],"answer":3},{"q":"<p><code dir=\"ltr\">handleRemove</code> does <code dir=\"ltr\">const i = movies.findIndex((m) =&gt; m.id === id); movies.splice(i, 1); setMovies(movies);</code>. The movie does not disappear. Why?</p>","options":[{"text":"<code dir=\"ltr\">findIndex</code> returns -1 for every movie.","why":"It finds the index correctly. The problem comes after."},{"text":"<code dir=\"ltr\">splice</code> changed the existing array in place and the same array was passed back, so React saw no change.","why":"Correct. React compares with Object.is. Create a new array: <code dir=\"ltr\">setMovies(movies.filter((m) =&gt; m.id !== id))</code>."},{"text":"You must call <code dir=\"ltr\">setMovies</code> before changing the array.","why":"Order does not help. Any mutation of the existing array leaves React with the same reference."},{"text":"Arrays cannot be stored in state.","why":"Arrays are a normal kind of state; they just have to be replaced, not mutated."}],"answer":1},{"q":"<p>You click Add, the new movie appears for a moment, then the page reloads and it is gone. What is missing?</p>","options":[{"text":"A <code dir=\"ltr\">key</code> on the new list item.","why":"A missing key causes a console warning, not a page reload."},{"text":"<code dir=\"ltr\">useEffect</code> to save the movie.","why":"Persistence would help after a reload, but the real bug is that the page reloads at all."},{"text":"<code dir=\"ltr\">e.preventDefault()</code> at the start of the form’s submit handler.","why":"Correct. Without it, the browser performs a normal form submission and reloads the page."},{"text":"<code dir=\"ltr\">type=&quot;button&quot;</code> on the Add button.","why":"That stops the button from submitting the form at all, so Enter and the submit handler would no longer work."}],"answer":2},{"q":"<p>This timer counts up by 2 every second in development. What is the fix?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"jsx\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">JSX</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">useEffect</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(() </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=></span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">  setInterval</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(() </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=></span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> setSeconds</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">((</span><span style=\"color:#953800;--shiki-dark:#FFA657\">s</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=></span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> s </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">), </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1000</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}, []);</span></span></code></pre></div>\n","options":[{"text":"Return a cleanup: <code dir=\"ltr\">const id = setInterval(…); return () =&gt; clearInterval(id);</code>","why":"Correct. StrictMode mounts, cleans up and mounts again; without a cleanup the first interval keeps running beside the second."},{"text":"Remove StrictMode so the Effect runs once.","why":"That hides the bug in development, but the missing cleanup still leaks an interval whenever the component unmounts."},{"text":"Add <code dir=\"ltr\">seconds</code> to the dependency array.","why":"That would restart the Effect every second and, still without a cleanup, pile up even more intervals."},{"text":"Use <code dir=\"ltr\">setSeconds(seconds + 1)</code> instead of the updater.","why":"The updater is correct here. The doubled speed comes from two intervals running at once."}],"answer":0},{"q":"<p><code dir=\"ltr\">SearchBox</code> keeps <code dir=\"ltr\">query</code> in its own state. <code dir=\"ltr\">MovieList</code>, its sibling, must show only movies whose title contains the query. What do you do?</p>","options":[{"text":"Have SearchBox write the query to localStorage and MovieList read it every render.","why":"MovieList would not re-render when the query changes, and storage is the wrong tool for sharing state."},{"text":"Give MovieList its own <code dir=\"ltr\">query</code> state and copy it from SearchBox with an Effect.","why":"Two copies synced by an Effect are slower and can disagree. One owner is simpler."},{"text":"Render MovieList inside SearchBox so it can read the state.","why":"That bends the UI structure around the data and breaks the layout."},{"text":"Move <code dir=\"ltr\">query</code> to their common parent, pass it to both, and pass a change handler to SearchBox.","why":"Correct. Lifting state gives it one owner, and both siblings read the same value."}],"answer":3}],"s-rf-4":[{"q":"<p>After your first Vercel deploy, the site is blank and the console shows a 404 for <code dir=\"ltr\">/src/main.jsx</code>. What went wrong?</p>","options":[{"text":"Vercel served the source <code dir=\"ltr\">index.html</code> instead of the build. Check the framework preset is Vite and the output directory is <code dir=\"ltr\">dist</code>.","why":"Correct. The root index.html only works through the Vite dev server. The built files in dist/ are what should be served."},{"text":"React 19 is not supported on Vercel yet.","why":"Vercel serves static files; it does not care which React version built them."},{"text":"<code dir=\"ltr\">main.jsx</code> must be renamed to <code dir=\"ltr\">main.js</code> for production.","why":"The file extension is not the issue. In a correct build, main.jsx is compiled into a bundle and is never requested."},{"text":"The app needs a <code dir=\"ltr\">vercel.json</code> rewrite to <code dir=\"ltr\">/src/main.jsx</code>.","why":"Pointing to source files would still fail; browsers cannot run JSX."}],"answer":0},{"q":"<p>A button should be indigo when <code dir=\"ltr\">active</code> is true. Which className works reliably with Tailwind?</p>","options":[{"text":"<code dir=\"ltr\">`bg-${active ? &quot;indigo&quot; : &quot;slate&quot;}-600`</code>","why":"Tailwind never sees the full class names, so neither background is generated."},{"text":"<code dir=\"ltr\">active ? &quot;bg-indigo-600 text-white&quot; : &quot;bg-slate-100&quot;</code>","why":"Correct. Both complete class names appear in the source, so Tailwind generates them."},{"text":"<code dir=\"ltr\">&quot;bg-&quot; + color + &quot;-600&quot;</code> with <code dir=\"ltr\">color</code> from props","why":"Building names from pieces has the same problem: the full classes never appear in the source."},{"text":"<code dir=\"ltr\">style={{ className: &quot;bg-indigo-600&quot; }}</code>","why":"<code dir=\"ltr\">className</code> is not a CSS property, so this sets nothing."}],"answer":1},{"q":"<p>In the finished Watchlist, which value should not be stored in <code dir=\"ltr\">useState</code>?</p>","options":[{"text":"The array of movies.","why":"Movies change when the user adds, toggles or removes them, so they are real state."},{"text":"The selected filter.","why":"The filter changes when the user clicks a filter button and cannot be computed from anything else."},{"text":"The number of unwatched movies.","why":"Correct. It is derived from the movies during render, so storing it only creates a copy that can go stale."},{"text":"The text typed in the add form, inside AddMovieForm.","why":"The draft text changes as the user types and lives in the form. It is real state."}],"answer":2},{"q":"<p>You want to send a pull request with a restyled filter bar and let a friend check it on their phone before it goes live. What does Vercel give you?</p>","options":[{"text":"Nothing until you merge, because only main is built.","why":"With the Git integration, every pushed branch is built."},{"text":"A production deploy of the branch, replacing the live site.","why":"Production only changes from the production branch."},{"text":"A ZIP file of the build to send to your friend.","why":"Vercel deploys builds to URLs; sharing files is not part of the flow."},{"text":"A preview deployment with its own URL, posted on the pull request.","why":"Correct. Preview URLs let anyone check a change without touching production."}],"answer":3},{"q":"<p>Which piece of Watchlist code belongs in an Effect?</p>","options":[{"text":"Writing the movies to localStorage whenever they change.","why":"Correct. Keeping an outside system in sync with state is exactly what Effects are for."},{"text":"Computing the list of visible movies from the filter.","why":"That is derived data. Calculate it during render."},{"text":"Clearing the title input after the user submits the form.","why":"That is caused by a specific action, so it belongs in the submit handler."},{"text":"Adding a movie when the form is submitted.","why":"User actions are handled in event handlers, not Effects."}],"answer":0}]},"final":[{"q":"<p>A component increments a module-level <code dir=\"ltr\">renderCount</code> variable in its body and shows it. The number is different in development and production. Why?</p>","options":[{"text":"Vite caches modules differently in production.","why":"Module caching does not change how many times React calls your component."},{"text":"The component is impure: StrictMode renders it twice in development, so the side effect runs twice.","why":"Correct. Rendering must not change anything outside the component. Move side effects to handlers or Effects."},{"text":"Production builds remove module-level variables.","why":"Module variables still exist in production; only the number of renders differs."},{"text":"React 19 renders every component twice in production.","why":"Production renders once. The double render is a development-only check."}],"answer":1},{"q":"<p>Which expression shows the text “Watched” only when <code dir=\"ltr\">movie.watched</code> is true, and nothing otherwise?</p>","options":[{"text":"<code dir=\"ltr\">{movie.watched ? &quot;Watched&quot;}</code>","why":"A ternary needs both branches; this is a syntax error."},{"text":"<code dir=\"ltr\">{if (movie.watched) &quot;Watched&quot;}</code>","why":"<code dir=\"ltr\">if</code> is a statement and cannot go inside JSX braces."},{"text":"<code dir=\"ltr\">{movie.watched &amp;&amp; &quot;Watched&quot;}</code>","why":"Correct. When <code dir=\"ltr\">watched</code> is false the expression is false, and React renders nothing for false."},{"text":"<code dir=\"ltr\">{movie.watched || &quot;Watched&quot;}</code>","why":"<code dir=\"ltr\">||</code> returns “Watched” when watched is false, the opposite of what you want, and renders nothing visible when it is true."}],"answer":2},{"q":"<p>You type in a list row’s input, and it loses focus after every keystroke. The list uses <code dir=\"ltr\">key={Math.random()}</code>. What is happening?</p>","options":[{"text":"Every render produces new keys, so React treats each row as new, destroys it and creates a fresh input.","why":"Correct. Keys must be stable. Use an id stored with each item."},{"text":"Inputs inside lists cannot be controlled.","why":"Controlled inputs work in lists. The changing key is what remounts the row."},{"text":"<code dir=\"ltr\">Math.random()</code> can produce duplicate keys.","why":"Duplicates are possible but rare. The real problem is that the keys change on every render."},{"text":"React limits how often a list can re-render.","why":"There is no such limit. The rows are being recreated because their identity changes."}],"answer":0},{"q":"<p>Inside a click handler you call <code dir=\"ltr\">setFilter(&quot;watched&quot;)</code> and then <code dir=\"ltr\">console.log(visible.length)</code>, where <code dir=\"ltr\">visible</code> is derived from <code dir=\"ltr\">filter</code> during render. What is logged?</p>","options":[{"text":"The number of watched movies.","why":"The new filter applies in the next render. This handler still sees the old <code dir=\"ltr\">visible</code>."},{"text":"0, because state is reset while updating.","why":"State is never reset by an update; the old snapshot stays intact until the next render."},{"text":"An error, because derived values cannot be read in handlers.","why":"Handlers can read anything from their render. They just read that render’s values."},{"text":"The length from the current render, based on the old filter.","why":"Correct. Each render is a snapshot; the new value appears in the next render."}],"answer":3},{"q":"<p>The Watchlist stores <code dir=\"ltr\">visibleMovies</code> in state and updates it when the filter changes. Newly added movies do not appear until the filter is clicked again. What is the best fix?</p>","options":[{"text":"Also update <code dir=\"ltr\">visibleMovies</code> in the add handler.","why":"That patches one case. Toggle and remove would still need the same fix, and the next feature will forget it."},{"text":"Remove the <code dir=\"ltr\">visibleMovies</code> state and compute it during render from <code dir=\"ltr\">movies</code> and <code dir=\"ltr\">filter</code>.","why":"Correct. A derived value computed on every render is always in sync with its sources."},{"text":"Sync it with an Effect that depends on <code dir=\"ltr\">movies</code> and <code dir=\"ltr\">filter</code>.","why":"It works after an extra render with stale data, and keeps the unnecessary duplicate state."},{"text":"Store the filter inside each movie object.","why":"The filter is a property of the view, not of each movie. This makes updates harder."}],"answer":1},{"q":"<p>As soon as the page loads, React reports “Too many re-renders”. The list items contain <code dir=\"ltr\">&lt;button onClick={handleRemove(movie.id)}&gt;Remove&lt;/button&gt;</code>. What is the fix?</p>","options":[{"text":"Wrap <code dir=\"ltr\">handleRemove</code> in <code dir=\"ltr\">useEffect</code>.","why":"Event handling is not an Effect. The problem is that the handler is called during render."},{"text":"Change it to <code dir=\"ltr\">onClick={handleRemove}</code> and read the id from the event.","why":"React would pass the click event, not the id, so the handler would remove nothing."},{"text":"Pass a function: <code dir=\"ltr\">onClick={() =&gt; handleRemove(movie.id)}</code>.","why":"Correct. The arrow function runs only on click, and then calls the handler with the right id."},{"text":"Use <code dir=\"ltr\">onMouseUp</code> instead of <code dir=\"ltr\">onClick</code>.","why":"Any event prop has the same problem when given the result of a call instead of a function."}],"answer":2},{"q":"<p>A “Watched” checkbox is written as <code dir=\"ltr\">&lt;input type=&quot;checkbox&quot; value={watched} onChange={(e) =&gt; setWatched(e.target.value)} /&gt;</code>. Clicking it never shows a check mark. What is wrong?</p>","options":[{"text":"Checkboxes cannot be controlled in React.","why":"They can; they just use a different attribute."},{"text":"The handler needs <code dir=\"ltr\">e.preventDefault()</code>.","why":"Preventing the default would stop the checkbox from toggling at all."},{"text":"<code dir=\"ltr\">watched</code> must be a string.","why":"A boolean is the right type for a checkbox. The issue is which property is read and set."},{"text":"Checkboxes use <code dir=\"ltr\">checked</code> and <code dir=\"ltr\">e.target.checked</code>, not <code dir=\"ltr\">value</code>.","why":"Correct. <code dir=\"ltr\">value</code> is the string submitted with a form; <code dir=\"ltr\">checked</code> is the on/off state."}],"answer":3},{"q":"<p>The Watchlist loads saved movies in <code dir=\"ltr\">useEffect(() =&gt; setMovies(load()), [])</code> and saves them in another Effect on <code dir=\"ltr\">[movies]</code>. Users report their list is sometimes wiped on reload. What is the better design?</p>","options":[{"text":"Load in the state initializer, <code dir=\"ltr\">useState(load)</code>, so the first render already has the saved movies.","why":"Correct. With an Effect, the first render saves the empty initial array before the load runs."},{"text":"Combine both Effects into one with no dependency array.","why":"That runs after every render and still saves before loading on the first one."},{"text":"Remove StrictMode so the Effects run once.","why":"The ordering problem exists in production too; StrictMode only makes it more visible."},{"text":"Save with <code dir=\"ltr\">setTimeout</code> to give the load time to finish.","why":"Timing hacks hide the problem and fail on slow devices. Load before the first render instead."}],"answer":0},{"q":"<p><code dir=\"ltr\">AddMovieForm</code> keeps the typed title in its own state; <code dir=\"ltr\">App</code> owns the movies. Where should the “clear the field after adding” logic live?</p>","options":[{"text":"In App, by passing a <code dir=\"ltr\">clear</code> prop down to the form.","why":"App does not own the draft text, so it should not manage it."},{"text":"In an Effect in the form that watches the movies list.","why":"The list also changes on toggle and remove, so the field would clear at the wrong times."},{"text":"In the form’s submit handler, right after calling <code dir=\"ltr\">onAdd</code>.","why":"Correct. The form owns the draft and the user action that should clear it."},{"text":"In MovieList, after it renders the new item.","why":"MovieList knows nothing about the form and should not reach into its state."}],"answer":2},{"q":"<p>You want the active filter button styled differently, and you already set <code dir=\"ltr\">aria-pressed={value === key}</code> on each one. Which Tailwind approach fits best?</p>","options":[{"text":"Add <code dir=\"ltr\">aria-pressed:bg-indigo-600 aria-pressed:text-white</code> to the button’s classes.","why":"Correct. The variant reads the same attribute screen readers announce, so the visuals and semantics stay in sync."},{"text":"Build the class with a template literal from the filter name.","why":"Tailwind cannot detect classes built from pieces, so they would not be generated."},{"text":"Add a <code dir=\"ltr\">useEffect</code> that sets the button’s style through the DOM.","why":"Reaching into the DOM for styling bypasses React and adds an Effect where none is needed."},{"text":"Create a <code dir=\"ltr\">tailwind.config.js</code> with an <code dir=\"ltr\">active</code> color.","why":"v4 needs no config file, and a color alone does not say when to apply it."}],"answer":0},{"q":"<p>Your app calls a paid movie API with <code dir=\"ltr\">import.meta.env.VITE_MOVIE_API_SECRET</code>. Why is this a problem?</p>","options":[{"text":"Vite does not support environment variables in production.","why":"Vite does support them; that is exactly how the value gets into the bundle."},{"text":"Vercel strips <code dir=\"ltr\">VITE_</code> variables from builds.","why":"Vercel passes them to the build, and Vite inlines them."},{"text":"The variable name is too long.","why":"Name length is irrelevant. Exposure is the problem."},{"text":"<code dir=\"ltr\">VITE_</code> values are inlined into the public JavaScript bundle, so anyone can read the secret.","why":"Correct. Keep secrets on a server, such as a serverless function, and call that from the client."}],"answer":3},{"q":"<p>You extract a <code dir=\"ltr\">Card</code> component that renders a border, padding and <code dir=\"ltr\">{children}</code>, and use it for movie items and the empty state. What is the main benefit?</p>","options":[{"text":"Cards render faster than divs.","why":"A component adds no rendering speed; it renders the same elements."},{"text":"The frame is defined once, so style changes happen in one place and each use only supplies its content.","why":"Correct. Composition with children separates the shared frame from the varying content."},{"text":"React requires every list item to be wrapped in a component.","why":"Plain elements work fine in lists. Extraction is a choice for reuse and clarity."},{"text":"It lets the empty state share state with the movie items.","why":"Components never share state just by using the same wrapper; each instance is independent."}],"answer":1}],"glossary":[{"id":"vite","term":"Vite","definition":"A build tool and dev server for front-end projects. It serves your source files with instant updates during development and bundles them into optimized static files in dist/ for production.","lesson":"l-rf-1-2"},{"id":"strict-mode","term":"StrictMode","definition":"A React wrapper component that adds development-only checks, such as rendering components twice and running Effects twice, to expose impure code and missing cleanups. It has no effect in production.","lesson":"l-rf-1-2"},{"id":"component","term":"Component","definition":"A JavaScript function whose name starts with a capital letter and that returns JSX. You use it like a tag, and React calls it to find out what to show.","lesson":"l-rf-1-3"},{"id":"fragment","term":"Fragment","definition":"A wrapper written as &lt;&gt;…&lt;/&gt; or <Fragment> that groups several elements without adding a DOM node, so a component can return siblings as one root.","lesson":"l-rf-1-3"},{"id":"jsx","term":"JSX","definition":"A syntax extension that lets you write HTML-like markup in JavaScript. A compiler turns each tag into a function call that creates a React element.","lesson":"l-rf-1-4"},{"id":"react-element","term":"React element","definition":"A plain JavaScript object, created by JSX, that describes what should appear on screen: a type such as “h2” or a component, plus its props. React turns elements into DOM.","lesson":"l-rf-1-4"},{"id":"derived-value","term":"Derived value","definition":"Data calculated during render from props or state, such as a count or a filtered list. It is never stored in state, so it can never drift out of sync with its source.","lesson":"l-rf-2-1"},{"id":"props","term":"Props","definition":"The inputs a parent passes to a component as attributes, received as one object. Props are read-only: a component never changes them, it receives new ones when the parent re-renders.","lesson":"l-rf-2-2"},{"id":"children-prop","term":"children","definition":"The prop that holds whatever is nested between a component’s opening and closing tags. Rendering {children} lets a component wrap content it knows nothing about.","lesson":"l-rf-2-3"},{"id":"slot","term":"Slot prop","definition":"A prop that accepts JSX, such as actions={<button>Shuffle</button>}, so the caller decides what appears and the component decides where it goes.","lesson":"l-rf-2-3"},{"id":"prop-drilling","term":"Prop drilling","definition":"Passing a prop through several components that don’t use it, only to reach a deeply nested one. Composition with elements or context can often remove it.","lesson":"l-rf-2-3"},{"id":"conditional-rendering","term":"Conditional rendering","definition":"Choosing what a component outputs based on data, using an early return, the ternary operator, or &amp;&amp; in JSX. Returning null renders nothing.","lesson":"l-rf-2-4"},{"id":"unmount","term":"Unmount","definition":"When React removes a component from the tree, destroying its DOM and its state. A conditionally rendered component unmounts when its condition becomes false.","lesson":"l-rf-2-4"},{"id":"key","term":"Key","definition":"A special prop on list items that tells React which item is which between renders. It must be unique among siblings and stable, usually an id from the data.","lesson":"l-rf-2-5"},{"id":"state","term":"State","definition":"Data a component remembers between renders, declared with useState. Calling its setter stores a new value and makes React render the component again.","lesson":"l-rf-3-1"},{"id":"hook","term":"Hook","definition":"A function whose name starts with “use”, such as useState or useEffect, that lets a component use React features. Hooks must be called at the top level of a component.","lesson":"l-rf-3-1"},{"id":"state-snapshot","term":"State snapshot","definition":"The fixed set of state values a single render sees. Setting state does not change the current variables; it schedules a new render with new values.","lesson":"l-rf-3-1"},{"id":"updater-function","term":"Updater function","definition":"A function passed to a state setter, as in setCount(© =&gt; c + 1). React calls it with the latest pending value, so several updates in a row add up correctly.","lesson":"l-rf-3-1"},{"id":"immutable-update","term":"Immutable update","definition":"Changing state by creating new arrays or objects (with spread, map or filter) instead of modifying the existing ones, so React can detect the change.","lesson":"l-rf-3-1"},{"id":"event-handler","term":"Event handler","definition":"A function passed to a prop such as onClick or onSubmit that React calls when the event happens. Handlers are where side effects caused by user actions belong.","lesson":"l-rf-3-2"},{"id":"event-bubbling","term":"Event bubbling","definition":"The way an event travels from the element where it happened up through its ancestors, triggering their handlers too. e.stopPropagation() stops it.","lesson":"l-rf-3-2"},{"id":"controlled-input","term":"Controlled input","definition":"A form field whose value comes from React state and whose onChange handler updates that state, making state the single source of truth for what the field shows.","lesson":"l-rf-3-3"},{"id":"form-action","term":"Form action","definition":"A React 19 feature where a function passed to a form’s action prop receives the submitted FormData. React prevents the page reload and resets uncontrolled fields afterwards.","lesson":"l-rf-3-3"},{"id":"use-action-state","term":"useActionState","definition":"A React 19 Hook that wraps an action function and returns the latest result it produced, a dispatch function to pass to a form, and an isPending flag.","lesson":"l-rf-3-3"},{"id":"lifting-state-up","term":"Lifting state up","definition":"Moving state from a component into the closest common parent of every component that needs it, then passing the value down and change handlers down as props.","lesson":"l-rf-3-4"},{"id":"effect","term":"Effect","definition":"Code passed to useEffect that runs after React updates the screen, used to synchronize with something outside React such as the document title, storage, timers or subscriptions.","lesson":"l-rf-3-5"},{"id":"dependency-array","term":"Dependency array","definition":"The second argument to useEffect listing every value the Effect reads. React re-runs the Effect only when one of those values has changed since the last render.","lesson":"l-rf-3-5"},{"id":"cleanup-function","term":"Cleanup function","definition":"A function returned from an Effect that undoes it, such as removing a listener or clearing a timer. React runs it before the Effect runs again and on unmount.","lesson":"l-rf-3-5"},{"id":"utility-class","term":"Utility class","definition":"A small CSS class that does one thing, such as p-4 for padding or text-slate-600 for color. Tailwind CSS generates the utilities your files use.","lesson":"l-rf-4-2"},{"id":"preview-deployment","term":"Preview deployment","definition":"A deployment of a non-production branch or pull request at its own unique URL, so changes can be checked before they are merged and reach the production site.","lesson":"l-rf-4-3"}]}