Hook Internals — Series 3

Preview — 3 of 10 questions

Is calling setSelected during render (not in an effect or handler) valid here?

javascript
function List({ items, selection }) {
  const [prevItems, setPrevItems] = useState(items);
  const [selected, setSelected] = useState(selection);

  if (items !== prevItems) {
    setPrevItems(items);
    setSelected(selection);   // ← setState during render
  }
  // ...
}
AYes — React explicitly supports calling a setter during render to adjust state in response to a prop change. React discards the in-progress render output and immediately re-renders the same component with the new state, before touching the DOM or rendering children. It is more efficient than doing the same adjustment in a useEffect (which would cause a visible extra commit)
BNo — setState during render always causes an infinite loop
CYes, but only inside useMemo
DNo — this throws "Cannot update during render"

Which statement is accurate?

javascript
'use client';
function LikeButton({ likes, likeAction }) {
  const [optimisticLikes, addOptimisticLike] = useOptimistic(likes, (state, delta) => state + delta);

  return (
    <form action={async () => { addOptimisticLike(1); await likeAction(); }}>
      <button>{optimisticLikes}</button>
    </form>
  );
}
AoptimisticLikes permanently diverges from likes after the first click
BaddOptimisticLike(1) applies the update function over the current base (likes) to produce optimisticLikes immediately, for the duration of the pending action. When the action settles and the component re-renders with an updated likes prop (e.g. after server revalidation), the optimistic layer is dropped and optimisticLikes snaps to the real likes. It must be called within an action/transition
CIt stores the optimistic value in localStorage
DIt only works with useReducer

What is the constraint on where useFormStatus can be called?

javascript
function SubmitButton() {
  const { pending } = useFormStatus();
  return <button disabled={pending}>{pending ? 'Saving…' : 'Save'}</button>;
}

function Form() {
  return <form action={saveAction}><SubmitButton /></form>;
}
AIt can be called anywhere in the app
BIt must be called in the same component as <form>
CuseFormStatus reads the status of the nearest parent <form>, so it must be called from a component rendered inside that <form> — not in the component that renders the <form> itself. That is why the submit button is factored into its own child component. It returns { pending, data, method, action }
DIt requires a formId argument

Sign up free to play

Answer all 10 questions (7 more), see explanations for every answer, and track your score.