Suggest an editImprove this articleRefine the answer for “What is useOptimistic”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)`useOptimistic()` is a React hook that lets you **temporarily show an updated state** in the UI while an asynchronous action is running (for example, submitting a form, adding a comment, deleting an item, and so on). **Key point:** it makes the interface responsive and "alive" even if the server request takes 1-2 seconds, and React itself rolls back the state if the operation ends in an error.Shown above the full answer for quick recall.Answer (EN)Image## What `useOptimistic()` is > `useOptimistic()` is a React hook that lets you **temporarily show an updated state** in the UI, > while an asynchronous action is running (for example, submitting a form, adding a comment, deleting an item, and so on). In other words: it helps make the interface responsive and "alive", even if the request to the server takes 1-2 seconds. --- ## Signature ```javascript const [optimisticState, addOptimistic] = useOptimistic(baseState, updateFn); ``` | Argument | Description | |---|---| | `baseState` | The current real state (for example, a list of comments, an array of tasks, etc.) | | `updateFn` | A function `(state, newValue) => newState` describing how to display the "optimistic" state | | **Returns** | `[optimisticState, addOptimistic]` - the current state (accounting for the optimism) and a function to temporarily change it | --- ## A real-life example Suppose you're building a chat where messages are sent to the server. The user clicks "Send", but the response from the API arrives after a second. Without optimism, the UI freezes - the message appears only after the response. With `useOptimistic()` you can show the new message **immediately**, and then React automatically updates the UI once the server responds. --- ## Example: adding a comment ```javascript import { useOptimistic, useActionState } from 'react'; async function postComment(prevState, formData) { const comment = formData.get('comment'); await api.addComment(comment); return { success: true }; } export default function Comments({ comments }) { const [state, formAction] = useActionState(postComment, null); const [optimisticComments, addOptimistic] = useOptimistic( comments, (currentComments, newComment) => [ ...currentComments, { id: Math.random(), text: newComment, pending: true }, ] ); async function handleSubmit(formData) { const comment = formData.get('comment'); addOptimistic(comment); // instantly show the new comment await formAction(formData); // wait for the server } return ( <form action={handleSubmit}> <ul> {optimisticComments.map(c => ( <li key={c.id}> {c.text} {c.pending && '(sending...)'} </li> ))} </ul> <input name="comment" /> <button type="submit">Send</button> </form> ); } ``` Here: - `useOptimistic` immediately creates a "virtual" list of comments with the new message; - When the server responds, React replaces the optimistic state with the real one; - The user **immediately** sees their comment appear. --- ## Other examples #### Deleting an item ```javascript const [optimisticTodos, removeOptimistic] = useOptimistic( todos, (current, id) => current.filter(t => t.id !== id) ); async function handleDelete(id) { removeOptimistic(id); // instantly hide it await api.deleteTodo(id); // the server confirms afterward } ``` #### Likes ```javascript const [optimisticLikes, toggleOptimistic] = useOptimistic( likes, (current, delta) => current + delta ); async function handleLike() { toggleOptimistic(1); await api.likePost(); } ``` --- ## How this works under the hood 1. **You keep the "real" state** (for example, `comments` or `likes`). 2. **React builds an "optimistic" state on top of it**, which is applied instantly. 3. When the Action finishes (or the data updates from the server), React **discards the optimistic state** and syncs with the real one. 4. If the operation ends in an error, React automatically "rolls back" the UI to the previous state. --- ## The difference from a manual approach (`useState`) Without `useOptimistic`, you would have to write: ```javascript setComments([...comments, newComment]); // manually try { await api.addComment(newComment); } catch { setComments(oldComments); // rollback } ``` Problems: - you need to keep the old state around for the rollback, - it's hard to sync with other updates, - it can conflict with concurrent rendering. With `useOptimistic`: - React itself tracks the "virtual" changes, - it automatically syncs and rolls back the state, - it works safely under concurrent rendering. --- ## When to use `useOptimistic` #### It fits for: - Interfaces with **response delays** (forms, comments, likes, carts); - **Lists and tables** where items are added/removed; - **UX optimization** - the user sees the action "instantly". #### It should not be used: - For data where an error must *block* the action (for example, payments); - For state that depends on complex server-side transactions; - When the "optimistic" version could confuse the user. --- ## Comparison with other React 19 hooks | Hook | Purpose | |---|---| | `useActionState()` | Manages the state of an asynchronous action (result, error, pending) | | `useFormStatus()` | Tracks the submission status of a specific form | | `useOptimistic()` | Temporarily updates the UI for instant feedback | | `useTransition()` | Makes updates "low priority", but not optimistic | --- ## Combined example: `useOptimistic` + `useActionState` ```javascript async function addTask(prev, formData) { const task = formData.get('task'); await api.addTask(task); return { success: true }; } export default function TaskList({ tasks }) { const [state, formAction] = useActionState(addTask, null); const [optimisticTasks, addOptimistic] = useOptimistic( tasks, (list, newTask) => [...list, { id: Math.random(), text: newTask, pending: true }] ); async function handleSubmit(formData) { const task = formData.get('task'); addOptimistic(task); await formAction(formData); } return ( <form action={handleSubmit}> <ul> {optimisticTasks.map(t => ( <li key={t.id}>{t.text} {t.pending && '(saving...)'}</li> ))} </ul> <input name="task" /> <button type="submit">Add</button> </form> ); } ``` The user sees the new task **instantly**, and React finalizes it once the server confirms. --- ## Summary > `useOptimistic()` is a React hook for building an *instant UI response* > to asynchronous changes, while the server processes the action. > > It is perfect for UX where the sense of "speed" matters, > while React itself manages the rollback and data reconciliation.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.