Keep Async React Callbacks Fresh: A Deep Dive into the useLatest Hook

Why Async Callbacks Often Miss the Latest State

In modern React applications, asynchronous operations such as API calls, timers, or event listeners frequently run after a component has re‑rendered. When a function captures state at the moment of its creation, it forms a closure that may reference an outdated value once the async work completes. This “stale closure” problem can cause UI inconsistencies, such as an autosave button indicating a successful save while the user continues typing.

Illustrative Example: An Autosave Button with Stale State

function Editor({ docId }) {
  const [text, setText] = useState("");
  const [status, setStatus] = useState("idle");

  async function save() {
    setStatus("saving");
    await api.save(docId, text); // captures "text" from the time save() was called
    setStatus("saved"); // ⚠️ user may have typed during await
  }

  return (
    
      

Close filters
Products Search