Extraordinary React hooks for optimistic UI updates with automatic rollback on failure. Make your React apps feel instant with zero effort.
Optimistic updates make your app feel instant, but handling rollbacks manually is error-prone and tedious. This library manages all the complexity for you — apply changes immediately, rollback automatically on failure, and handle multiple simultaneous mutations correctly.
npm install @chemmangat/optimistic-updateimport { useOptimisticList } from '@chemmangat/optimistic-update'
const { items, addItem, removeItem, updateItem } = useOptimisticList(todos, {
idKey: 'id',
onError: (err) => toast.error(err.message),
})
await addItem(newTodo, async () => {
await fetch('/api/todos', { method: 'POST', body: JSON.stringify(newTodo) })
})import { useOptimisticValue } from '@chemmangat/optimistic-update'
const { value, update } = useOptimisticValue(count, {
onSuccess: () => console.log('Updated!'),
})
await update(value + 1, async () => {
await fetch('/api/increment', { method: 'POST' })
})import { useOptimisticMap } from '@chemmangat/optimistic-update'
const { map, set, remove, clear } = useOptimisticMap(userMap, {
onError: (err) => console.error(err),
})
await set('user-1', userData, async () => {
await fetch('/api/users/user-1', { method: 'PUT', body: JSON.stringify(userData) })
})import { useOptimisticSet } from '@chemmangat/optimistic-update'
const { set, add, remove, clear } = useOptimisticSet(tags, {
onSuccess: () => console.log('Tag updated!'),
})
await add('react', async () => {
await fetch('/api/tags', { method: 'POST', body: JSON.stringify({ tag: 'react' }) })
})- ⚡ Lightning Fast - Updates happen instantly in the UI
- 🔄 Auto Rollback - Automatic rollback on failure
- 🔒 Type Safe - Full TypeScript support with generics
- 🎯 Zero Dependencies - Only requires React
- 🧹 Auto Cleanup - Handles component unmount gracefully
- 🎭 Concurrent Safe - Multiple simultaneous mutations work correctly
All hooks accept similar options:
{
onError?: (error: Error) => void // Called when rollback happens
onSuccess?: () => void // Called when mutation succeeds
}- You call
addItem,removeItem, orupdateItem - The UI updates immediately (optimistic)
- The
mutationFnruns in the background - If it succeeds → optimistic state becomes real
- If it fails → automatically rolls back to the exact previous state (including order)
Multiple simultaneous mutations are handled independently — each can succeed or fail without affecting the others.
This is a monorepo containing:
packages/core- The npm package with all hooksapp/- Next.js demo application
All hooks are fully typed with generics:
interface User {
userId: string
name: string
email: string
}
const { items, updateItem } = useOptimisticList<User>(users, {
idKey: 'userId',
})
// TypeScript infers Partial<User> for updates
updateItem('123', { name: 'New Name' }, mutationFn)Try it live: Demo
Toggle "Simulate Failure" to see automatic rollback in action.
npm install
npm run devVisit http://localhost:3000 to see the demo.
npm run build:core
cd packages/core
npm publishMIT