[{"id":"set-state-three-times","domain":"general","topic":"Several setState calls in one handler","kind":"code","options":["a","b","c","d"],"answer":"b","rev":1,"gapFor":["other"],"fixes":["Use an updater function","Compute the next value once"]},{"id":"mutate-state-object","domain":"general","topic":"Mutating an object in state","kind":"code","options":["a","b","c","d"],"answer":"b","rev":1,"gapFor":["other"],"fixes":["Pass a new object","Use an updater"]},{"id":"ref-change-no-rerender","domain":"general","topic":"Changing ref.current","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["other"],"fixes":["Use state for what the screen shows"]},{"id":"stale-closure-interval","domain":"general","topic":"Stale state in setInterval","kind":"code","options":["a","b","c","d"],"answer":"b","rev":1,"gapFor":["other"],"fixes":["Use an updater function","Add count to the dependencies"]},{"id":"prop-copied-into-state","domain":"general","topic":"Copying a prop into state","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["other"],"fixes":["Use the prop directly","Reset with a key when you mean it","Name it as an initial value"]},{"id":"index-key-reorder","domain":"general","topic":"Index as key on reorder","kind":"code","options":["a","b","c","d"],"answer":"b","rev":1,"gapFor":["other"],"fixes":["Key by a stable ID from the data"]},{"id":"hook-after-early-return","domain":"general","topic":"Calling a hook conditionally","kind":"code","options":["a","b","c","d"],"answer":"b","rev":1,"gapFor":["other"],"fixes":["Call hooks before any early return","Split the component"]},{"id":"strict-mode-effect-twice","domain":"general","topic":"Strict Mode runs effects twice","kind":"code","options":["a","b","c","d"],"answer":"b","rev":1,"gapFor":["next-pages","other"],"fixes":["Return a cleanup"]},{"id":"fetch-effect-race","domain":"general","topic":"Fetch in an effect without cleanup","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["next-pages","other"],"fixes":["Ignore stale responses in cleanup","Use a data-fetching library"]},{"id":"object-dependency-loop","domain":"general","topic":"Object dependency in an effect","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["other"],"fixes":["Create the object inside the effect","Memoize it"]},{"id":"ref-as-prop-react-19","domain":"general","topic":"ref as a prop in React 19","kind":"code","options":["a","b","c","d"],"answer":"a","rev":1,"gapFor":["react-spa","next-pages","next-app-legacy","other"],"fixes":["Type the ref prop","On React 18, use forwardRef"]},{"id":"context-value-object","domain":"general","topic":"Context value as a new object","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["other"],"fixes":["Memoize the value","Move unrelated state down"]},{"id":"use-action-state-arguments","domain":"general","topic":"useActionState arguments","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["react-spa","next-pages","next-app-legacy","other"],"fixes":["Take the previous state first","Use the pending flag it gives you"]},{"id":"use-optimistic-rollback","domain":"general","topic":"useOptimistic when the action fails","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["react-spa","next-pages","next-app-legacy","other"],"fixes":["Tell the user why it reverted","Keep addLike inside an Action"]},{"id":"use-uncached-promise","domain":"general","topic":"use() with a promise made in render","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["react-spa","next-pages","next-app-legacy","other"],"fixes":["Create it in a Server Component","Use a Suspense-ready library"]},{"id":"component-defined-inside-component","domain":"general","topic":"A component defined inside another","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["other"],"fixes":["Declare it at the top level"]},{"id":"and-operator-renders-zero","domain":"general","topic":"A number on the left of &&","kind":"code","options":["a","b","c","d"],"answer":"b","rev":1,"gapFor":["other"],"fixes":["Make the left side a boolean","Use a ternary"]},{"id":"use-state-replaces-object","domain":"general","topic":"useState doesn't merge objects","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["other"],"fixes":["Copy the old fields","Use an updater","Split unrelated fields"]},{"id":"initial-state-called-every-render","domain":"general","topic":"useState(expensive())","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["other"],"fixes":["Pass an initializer function","Or wrap it in an arrow"]},{"id":"effect-cleanup-on-dep-change","domain":"general","topic":"Effect cleanup when deps change","kind":"code","options":["a","b","c","d"],"answer":"a","rev":1,"gapFor":["other"],"fixes":["Make cleanup undo its own setup"]},{"id":"error-boundary-event-handler","domain":"general","topic":"Error boundaries and event handlers","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["next-pages","next-app-legacy","other"],"fixes":["Catch it and put it in state","Throw inside startTransition"]},{"id":"portal-event-bubbling","domain":"general","topic":"Events from a portal","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["react-spa","next-pages","next-app-legacy","other"],"fixes":["Stop propagation in the portal","Move the portal out of the div"]},{"id":"memo-inline-callback","domain":"general","topic":"memo with an inline callback","kind":"code","options":["a","b","c"],"answer":"c","rev":1,"gapFor":["other"],"fixes":["Cache the callback","Turn on the React Compiler"]},{"id":"measure-in-use-effect-flicker","domain":"general","topic":"Measuring layout in useEffect","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["other"],"fixes":["Use useLayoutEffect"]},{"id":"suspense-fallback-hides-content","domain":"general","topic":"Suspense fallback on a tab switch","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["react-spa","next-pages","other"],"fixes":["Switch tabs in a Transition"]},{"id":"use-deferred-value-stale","domain":"general","topic":"useDeferredValue while loading","kind":"code","options":["a","b","c","d"],"answer":"a","rev":1,"gapFor":["react-spa","next-pages","next-app-legacy","other"],"fixes":["Show that the list is stale"]},{"id":"form-action-resets-fields","domain":"general","topic":"<form action> resets fields","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["react-spa","next-pages","next-app-legacy","other"],"fixes":["Control the field"]},{"id":"title-children-single-string","domain":"general","topic":"<title> in a component","kind":"code","options":["a","b","c","d"],"answer":"b","rev":1,"gapFor":["react-spa","next-pages","next-app-legacy","other"],"fixes":["Build one string"]},{"id":"use-context-after-early-return","domain":"general","topic":"use(Context) after an early return","kind":"code","options":["a","b","c"],"answer":"a","rev":1,"gapFor":["react-spa","next-pages","next-app-legacy","other"],"fixes":["With useContext, read it first"]},{"id":"scroll-before-dom-update","domain":"general","topic":"Reading the DOM right after setState","kind":"code","options":["a","b","c"],"answer":"b","rev":1,"gapFor":["react-spa","next-pages","next-app-legacy","other"],"fixes":["Flush the update first"]}]