Quiz - Hooks for holding state
A component seeds its state by reading and parsing a draft out of localStorage. Which call does that read-and-parse work exactly once, on mount?
useState(parseDraft(getStoredDraft()))useState(() => parseDraft(getStoredDraft()))useState<Draft>(parseDraft(getStoredDraft()))parseDraft(getStoredDraft()) on every render and throws all but the first result away — wasted work on every keystroke. The annotation only fixes types; it does nothing about when the work runs.You’re holding the setTimeout ID that debounces a search input. Why is this a useRef and not a useState?
useState can only hold objects.useRef survives re-renders while a useState value is reset to its initial value on each render..current never re-renders, which is exactly right for a value the user never sees. The type claim is false, and useState also survives renders — the difference is that updating it forces a render you don’t want here.A junior keeps fullName in its own useState and resyncs it with a useEffect watching firstName and lastName. Beyond the extra render, what is the more dangerous problem with this shape?
fullName is a second copy of data that already exists, kept current by hand — add a middleName and forget the dependency array, and it silently goes stale with no error.useEffect can only depend on one value, so watching both names is unsupported.const fullName = firstName + ' ' + lastName can’t drift because there’s nothing to keep in sync. The concatenation is rounding error next to the render, and effects can depend on any number of values.A list view has a search filter the user types into. A teammate argues it should live in the URL as ?q=... rather than in lifted useState. Which facts actually justify the URL home? Select all that apply.
A submit form tracks isSubmitting, isSaved, submitError, and more across separate useStates, and a bug lets the spinner stay on after a validation failure. What is the core reason modelling this as a useReducer with a single status field fixes the class of bug?
status that means both — instead of merely discouraged.useState calls.await inside the reducer guarantees the spinner is reset on every exit path.status with a fixed set of legal values, so the illegal combinations can’t be constructed. A reducer is often more code, not less — and async must never live in the reducer; it stays in the handler that brackets the await with dispatches.A teammate proposes using crypto.randomUUID() instead of useId() to generate the id that links a <label> to its <input>, reasoning it’s “more unique.” What goes wrong?
crypto.randomUUID() is too slow to call during render.id attribute.useId is deterministic across the server boundary because it derives from the component’s position in the tree; a random generator runs twice and produces two different strings, breaking hydration. The same crypto.randomUUID() is the right tool when minted once at item creation and stored on the data — just not for a render-time ARIA id.Quiz complete
Score by topic