---
title: useOptimistic
---
`useOptimistic` is a React Hook that lets you optimistically update the UI.
```js
const [optimisticState, setOptimistic] = useOptimistic(value, reducer?);
```
---
## Reference {/*reference*/}
### `useOptimistic(value, reducer?)` {/*useoptimistic*/}
Call `useOptimistic` at the top level of your component to create optimistic state for a value.
```js
import { useOptimistic } from 'react';
function MyComponent({name, todos}) {
const [optimisticAge, setOptimisticAge] = useOptimistic(28);
const [optimisticName, setOptimisticName] = useOptimistic(name);
const [optimisticTodos, setOptimisticTodos] = useOptimistic(todos, todoReducer);
// ...
}
```
[See more examples below.](#usage)
#### Parameters {/*parameters*/}
* `value`: The value returned when there are no pending Actions.
* **optional** `reducer(currentState, action)`: The reducer function that specifies how the optimistic state gets updated. It must be pure, should take the current state and reducer action arguments, and should return the next optimistic state.
#### Returns {/*returns*/}
`useOptimistic` returns an array with exactly two values:
1. `optimisticState`: The current optimistic state. It is equal to `value` unless an Action is pending, in which case it is equal to the state returned by `reducer` (or the value passed to the set function if no `reducer` was provided).
2. The [`set` function](#setoptimistic) that lets you update the optimistic state to a different value inside an Action.
---
### `set` functions, like `setOptimistic(optimisticState)` {/*setoptimistic*/}
The `set` function returned by `useOptimistic` lets you update the state for the duration of an [Action](reference/react/useTransition#functions-called-in-starttransition-are-called-actions). You can pass the next state directly, or a function that calculates it from the previous state:
```js
const [optimisticLike, setOptimisticLike] = useOptimistic(false);
const [optimisticSubs, setOptimisticSubs] = useOptimistic(subs);
function handleClick() {
startTransition(async () => {
setOptimisticLike(true);
setOptimisticSubs(a => a + 1);
await saveChanges();
});
}
```
#### Parameters {/*setoptimistic-parameters*/}
* `optimisticState`: The value that you want the optimistic state to be during an [Action](reference/react/useTransition#functions-called-in-starttransition-are-called-actions). If you provided a `reducer` to `useOptimistic`, this value will be passed as the second argument to your reducer. It can be a value of any type.
* If you pass a function as `optimisticState`, it will be treated as an _updater function_. It must be pure, should take the pending state as its only argument, and should return the next optimistic state. React will put your updater function in a queue and re-render your component. During the next render, React will calculate the next state by applying the queued updaters to the previous state similar to [`useState` updaters](/reference/react/useState#setstate-parameters).
#### Returns {/*setoptimistic-returns*/}
`set` functions do not have a return value.
#### Caveats {/*setoptimistic-caveats*/}
* The `set` function must be called inside an [Action](reference/react/useTransition#functions-called-in-starttransition-are-called-actions). If you call the setter outside an Action, [React will show a warning](#an-optimistic-state-update-occurred-outside-a-transition-or-action) and the optimistic state will briefly render.
#### How optimistic state works {/*how-optimistic-state-works*/}
`useOptimistic` lets you show a temporary value while a Action is in progress:
```js
const [value, setValue] = useState('a');
const [optimistic, setOptimistic] = useOptimistic(value);
startTransition(async () => {
setOptimistic('b');
const newValue = await saveChanges('b');
setValue(newValue);
});
```
When the setter is called inside an Action, `useOptimistic` will trigger a re-render to show that state while the Action is in progress. Otherwise, the `value` passed to `useOptimistic` is returned.
This state is called the "optimistic" because it is used to immediately present the user with the result of performing an Action, even though the Action actually takes time to complete.
**How the update flows**
1. **Update immediately**: When `setOptimistic('b')` is called, React immediately renders with `'b'`.
2. **(Optional) await in Action**: If you await in the Action, React continues showing `'b'`.
3. **Transition scheduled**: `setValue(newValue)` schedules an update to the real state.
4. **(Optional) wait for Suspense**: If `newValue` suspends, React continues showing `'b'`.
5. **Single render commit**: Finally, the `newValue` is commits for `value` and `optimistic`.
There's no extra render to "clear" the optimistic state. The optimistic and real state converge in the same render when the Transition completes.
#### Optimistic state is temporary {/*optimistic-state-is-temporary*/}
Optimistic state is only renders while an Action is in progress, otherwise `value` is rendered.
If `saveChanges` returned `'c'`, then both `value` and `optimistic` will be `'c'`, not `'b'`.
**How the final state is determined**
The `value` argument to `useOptimistic` determines what displays after the Action finishes. How this works depends on the pattern you use:
- **Hardcoded values** like `useOptimistic(false)`: After the Action, `state` is still `false`, so the UI shows `false`. This is useful for pending states where you always start from `false`.
- **Props or state passed in** like `useOptimistic(isLiked)`: If the parent updates `isLiked` during the Action, the new value is used after the Action completes. This is how the UI reflects the result of the Action.
- **Reducer pattern** like `useOptimistic(items, fn)`: If `items` changes while the Action is pending, React re-runs your `reducer` with the new `items` to recalculate the state. This keeps your optimistic additions on top of the latest data.
**What happens when the Action fails**
If the Action throws an error, the Transition still ends, and React renders with whatever `value` currently is. Since the parent typically only updates `value` on success, a failure means `value` hasn't changed, so the UI shows what it showed before the optimistic update. You can catch the error to show a message to the user.
---
## Usage {/*usage*/}
### Adding optimistic state to a component {/*adding-optimistic-state-to-a-component*/}
Call `useOptimistic` at the top level of your component to declare one or more optimistic states.
```js [[1, 4, "age"], [1, 5, "name"], [1, 6, "todos"], [2, 4, "optimisticAge"], [2, 5, "optimisticName"], [2, 6, "optimisticTodos"], [3, 4, "setOptimisticAge"], [3, 5, "setOptimisticName"], [3, 6, "setOptimisticTodos"], [4, 6, "reducer"]]
import { useOptimistic } from 'react';
function MyComponent({age, name, todos}) {
const [optimisticAge, setOptimisticAge] = useOptimistic(age);
const [optimisticName, setOptimisticName] = useOptimistic(name);
const [optimisticTodos, setOptimisticTodos] = useOptimistic(todos, reducer);
// ...
```
`useOptimistic` returns an array with exactly two items:
1. The optimistic state, initially set to the value provided.
2. The set function that lets you temporarily change the state during an [Action](reference/react/useTransition#functions-called-in-starttransition-are-called-actions).
* If a reducer is provided, it will run before returning the optimistic state.
To use the optimistic state, call the `set` function inside an Action.
Actions are functions called inside `startTransition`:
```js {3}
function onAgeChange(e) {
startTransition(async () => {
setOptimisticAge(42);
const newAge = await postAge(42);
setAge(newAge);
});
}
```
React will render the optimistic state `42` first while the `age` remains the current age. The Action waits for POST, and then renders the `newAge` for both `age` and `optimisticAge`.
See [How optimistic state works](#how-optimistic-state-works) for a deep dive.
When using [Action props](/reference/react/useTransition#exposing-action-props-from-components), you can call the set function without `startTransition`:
```js [[3, 2, "setOptimisticName"]]
async function submitAction() {
setOptimisticName('Taylor');
await updateName('Taylor');
}
```
This works because Action props are already called inside `startTransition`.
For an example, see: [Using optimistic state in Action props](#using-optimistic-state-in-action-props).
---
### Using optimistic state in Action props {/*using-optimistic-state-in-action-props*/}
In an [Action prop](/reference/react/useTransition#exposing-action-props-from-components), you can call the optimistic setter directly without `startTransition`.
This example sets optimistic state inside a `