--- title: "usePredictive" publishedAt: "2026-10-01" summary: "React has useOptimistic for after you act. There's nothing for before." --- React has `useOptimistic`. You act, and the UI assumes success before the server confirms. The like turns red, the message shows up in the list, and if the server says no, it quietly reverts. That's for after you did something. There's nothing for before. `useOptimistic` = after you did something
`usePredictive` = before you do something ### Software needs to be proactive Most software waits. You open it, you click, it reacts. I think software needs to be proactive. It should move before I do, and do the boring part without me asking. Guillermo Rauch wrote about this in 2014, in his [7 principles of rich web applications](https://rauchg.com/2014/7-principles-of-rich-web-applications). Principle seven: predict behavior. Fetch the data when someone hovers a link, so it's ready when they click. Browsers have since built that in with the Speculation Rules API. I think there's a ladder here: 1. **Invisible.** The software prepares what you'll probably do. Prefetching. You never see it. 2. **Proposes.** The software shows you what you'll probably do, and you approve it. That's usePredictive. 3. **Acts.** The software just does it. Tags that delete themselves when nobody uses them. You don't need to do anything, the system cleans up after itself. Most products are stuck on the first step or jump straight to chat. The middle step, a good guess in the UI that you accept with one click, is where I'd want more software to be. ### This could've been a click Right now, most of that middle step happens in a chat. [Julian Lehr put it well](https://x.com/julianlehr/status/2093431829520847155): current LLM chat interfaces are a regression from GUIs. Actions that used to be links, buttons or keyboard shortcuts are now things you have to spell out in conversation. I'm kinda tired of chat interfaces too. I don't want the next step in text. I want it in the UI, right where I'd do it anyway, and I want to feel what comes next before I commit to it. And every team builds that UI from scratch. Dashboards, multi-step flows, onboarding, each with its own loading states, its own error handling, its own way of getting out of the way. Same boilerplate, every time. So I wanted a hook. ### useOptimistic, but before Same shape, other direction: ```ts const [optimisticState, addOptimistic] = useOptimistic(state, updateFn); const [prediction, dismiss] = usePredictive(state, predictFn); ``` You pass in the current state and a function that makes a guess. You get back the guess, or `null`, and a way to say "not now". Like useOptimistic, the guess is temporary. It belongs to the state it was made for, and when the state moves on, it's gone. How you guess is up to you: a few if-statements, the user's history, a model. React shouldn't care, and neither should the hook. ```tsx const [next, dismiss] = usePredictive( { step: project.step, members: project.members.length }, ({ step, members }) => { if (step === "created" && members === 1) return "Invite your team"; if (step === "invited") return "Connect a domain"; return null; }, ); if (!next) return null; return (

Next:

); ``` The guess can also come from a server or a model. `predictFn` can be async and gets an `AbortSignal`, so outdated guesses are cancelled. The whole hook is about 50 lines, one file, no dependencies. It's a sketch to copy and change, not a package: [usePredictive on GitHub](https://gist.github.com/nklswbr/297a0abe0a49a4e8129f9c1035594faf). ### One open question When you dismiss a guess, it stays gone until the state changes. Then a new guess can show up, even the same one. Is that right? Or should the hook remember what you said no to? I'm not sure yet. If you've built something like this, I'd love to hear how you did it. [DM me on X](https://x.com/nklswbr) or [send me an email](mailto:contact@nklswbr.com).