The useOptimistic
hook in React 19 is designed to handle optimistic updates. Optimistic updates allow you to update the UI immediately in response to a user action, assuming the operation will succeed, even before receiving confirmation from the server. This creates a smoother and more responsive user experience.
How useOptimistic
Works
- Initial State: You define the initial state of your data.
- Optimistic Update: When a user action occurs, the UI is updated immediately with the expected result.
- Server Response Handling: Once the server responds, the UI is updated again to confirm the optimistic update or revert to the original state if the operation fails.
- Error Handling: Any errors are caught and handled gracefully.
Examples
Here are five examples to illustrate how useOptimistic
can be used:
- Liking a Post
import { useOptimistic } from 'react';
function LikeButton({ postId }) {
const [likes, updateLikes] = useOptimistic(async (currentLikes) => {
const response = await fetch(`/api/like-post/${postId}`, { method: 'POST' });
if (!response.ok) throw new Error('Failed to like post');
return currentLikes + 1;
}, 0);
return (
<button onClick={() => updateLikes(likes + 1)}>
Like ({likes})
</button>
);
}
- Adding a Comment
import { useOptimistic } from 'react';
function CommentForm({ postId }) {
const [comments, addComment] = useOptimistic(async (newComment) => {
const response = await fetch(`/api/add-comment/${postId}`, {
method: 'POST',
body: JSON.stringify({ text: newComment }),
});
if (!response.ok) throw new Error('Failed to add comment');
return [...comments, newComment];
}, []);
const handleSubmit = (e) => {
e.preventDefault();
const newComment = e.target.elements.comment.value;
addComment(newComment);
};
return (
<form onSubmit={handleSubmit}>
<input name="comment" type="text" />
<button type="submit">Add Comment</button>
<ul>
{comments.map((comment, index) => (
<li key={index}>{comment}</li>
))}
</ul>
</form>
);
}
- Updating a Profile Name
import { useOptimistic } from 'react';
function ProfileEditor() {
const [name, updateName] = useOptimistic(async (newName) => {
const response = await fetch('/api/update-name', {
method: 'POST',
body: JSON.stringify({ name: newName }),
});
if (!response.ok) throw new Error('Failed to update name');
return newName;
}, 'John Doe');
return (
<div>
<input
type="text"
value={name}
onChange={(e) => updateName(e.target.value)}
/>
</div>
);
}
- Toggling a Todo Item
import { useOptimistic } from 'react';
function TodoItem({ todo }) {
const [completed, toggleCompleted] = useOptimistic(async (currentState) => {
const response = await fetch(`/api/toggle-todo/${todo.id}`, { method: 'POST' });
if (!response.ok) throw new Error('Failed to toggle todo');
return !currentState;
}, todo.completed);
return (
<div>
<input
type="checkbox"
checked={completed}
onChange={() => toggleCompleted(!completed)}
/>
{todo.text}
</div>
);
}
- Adding an Item to a Cart
import { useOptimistic } from 'react';
function AddToCartButton({ itemId }) {
const [cart, addToCart] = useOptimistic(async (currentCart) => {
const response = await fetch(`/api/add-to-cart/${itemId}`, { method: 'POST' });
if (!response.ok) throw new Error('Failed to add to cart');
return [...currentCart, itemId];
}, []);
return (
<button onClick={() => addToCart([...cart, itemId])}>
Add to Cart
</button>
);
}
Practice Exercises
Here are five practice exercises to help you get comfortable with useOptimistic
:
- Exercise 1: Create a form that allows users to submit their email address. Use
useOptimistic
to optimistically update the UI to show the email in a list before the server confirms the submission. - Exercise 2: Implement a “Follow” button for a social media profile. Use
useOptimistic
to immediately update the follower count when the button is clicked. - Exercise 3: Build a simple task manager where users can mark tasks as completed. Use
useOptimistic
to update the task’s status in the UI immediately. - Exercise 4: Create a voting system for a poll. Use
useOptimistic
to update the vote count for an option as soon as the user votes. - Exercise 5: Develop a shopping list application where users can add items to their list. Use
useOptimistic
to show the new item in the list immediately after the user adds it.
These exercises should help you get a good grasp of how to use the useOptimistic
hook in various scenarios.