Waiting for server confirmations before updating the UI feels sluggish. In real-world apps, users expect near-instant feedback. Enter optimistic updates: immediately reflect changes in the UI while the server catches up. Redux Toolkit makes this surprisingly clean — no extra libraries needed.
What Are Optimistic Updates?
Instead of waiting for a network response, you assume the action will succeed and update the UI instantly. If the server later responds with an error, you roll back or show a correction.
Step 1: Structure the Slice for Pending States
Let's model an optimistic update for a "like" feature:
// src/features/posts/postsSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios';
export const likePost = createAsyncThunk(
'posts/likePost',
async (postId) => {
await axios.post(`/api/posts/${postId}/like`);
return postId;
}
);
const postsSlice = createSlice({
name: 'posts',
initialState: {
posts: [],
error: null,
},
reducers: {
optimisticLike(state, action) {
const post = state.posts.find(p => p.id === action.payload);
if (post) {
post.likes++;
}
},
revertLike(state, action) {
const post = state.posts.find(p => p.id === action.payload);
if (post) {
post.likes--;
}
},
},
extraReducers: (builder) => {
builder
.addCase(likePost.fulfilled, (state, action) => {
// No-op because UI already updated optimistically
})
.addCase(likePost.rejected, (state, action) => {
state.error = 'Failed to like post';
});
},
});
export const { optimisticLike, revertLike } = postsSlice.actions;
export default postsSlice.reducer;
Step 2: Dispatch in the Right Order
In your React component:
// src/features/posts/LikeButton.js
import { useDispatch } from 'react-redux';
import { optimisticLike, revertLike, likePost } from './postsSlice';
function LikeButton({ postId }) {
const dispatch = useDispatch();
const handleLike = () => {
dispatch(optimisticLike(postId));
dispatch(likePost(postId)).unwrap().catch(() => {
dispatch(revertLike(postId));
});
};
return (
<button onClick={handleLike}>Like</button>
);
}
How It Works
- First,
optimisticLike
immediately increments likes in the local state. - Then,
likePost
sends the actual API request. - If the request fails,
revertLike
corrects the UI by decrementing.
Pros and Cons
✅ Pros
- Instant feedback for users
- Very little code overhead with Redux Toolkit
- Decouples UI responsiveness from server performance
⚠️ Cons
- Edge cases if the server state diverges (e.g., data race conditions)
- Rollback logic can become complex for more critical operations
🚀 Alternatives
- RTK Query: Handles optimistic updates natively if you use RTKQ for data fetching
- TanStack Query: (non-Redux) has built-in support for optimistic mutations
Summary
Optimistic updates aren't just for fancy apps — they're fundamental for great UX. With Redux Toolkit’s built-in capabilities, you can implement this advanced pattern cleanly without needing external dependencies.
If you found this useful, you can support me here: buymeacoffee.com/hexshift
Top comments (0)