Optimistic Updates with TanStack Query
++ Add todos to see optimistic updates in action. The server randomly fails + ~30% of the time so you can observe automatic rollback. +
+diff --git a/docs/config.json b/docs/config.json index 21737a41321..5e056704257 100644 --- a/docs/config.json +++ b/docs/config.json @@ -1555,12 +1555,8 @@ "to": "framework/react/examples/auto-refetching" }, { - "label": "Optimistic Updates (UI)", - "to": "framework/react/examples/optimistic-updates-ui" - }, - { - "label": "Optimistic Updates (Cache)", - "to": "framework/react/examples/optimistic-updates-cache" + "label": "Optimistic Updates", + "to": "framework/react/examples/nextjs-app-optimistic-updates" }, { "label": "Pagination", diff --git a/examples/react/optimistic-updates-cache/.gitignore b/examples/react/nextjs-app-optimistic-updates/.gitignore similarity index 67% rename from examples/react/optimistic-updates-cache/.gitignore rename to examples/react/nextjs-app-optimistic-updates/.gitignore index 4673b022e53..b988ee9758f 100644 --- a/examples/react/optimistic-updates-cache/.gitignore +++ b/examples/react/nextjs-app-optimistic-updates/.gitignore @@ -8,20 +8,27 @@ # testing /coverage +# next.js +/.next/ +/out/ + # production /build -pnpm-lock.yaml -yarn.lock -package-lock.json - # misc .DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local +*.pem +# debug npm-debug.log* yarn-debug.log* yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo diff --git a/examples/react/nextjs-app-optimistic-updates/README.md b/examples/react/nextjs-app-optimistic-updates/README.md new file mode 100644 index 00000000000..1069ea411bf --- /dev/null +++ b/examples/react/nextjs-app-optimistic-updates/README.md @@ -0,0 +1,61 @@ +# TanStack Query — Next.js App Router Optimistic Updates + +This example demonstrates **optimistic updates** with TanStack Query v5 in a Next.js 14 App Router project. + +## What it shows + +A todo list where items appear in the UI immediately after submission — before the server confirms. The server randomly fails ~30% of the time so you can observe automatic rollback behaviour. + +Two approaches are shown side by side via a tab toggle: + +### Approach 1 — Via UI Variables (simpler) + +Render the pending item directly from `mutation.variables`. No cache touching required. On error, the pending item simply disappears and an error message is shown. + +```ts +const mutation = useMutation({ mutationFn: addTodo, onSettled: invalidate }) + +// In JSX: +{mutation.isPending &&
+ Add todos to see optimistic updates in action. The server randomly fails + ~30% of the time so you can observe automatic rollback. +
+
+ Approach 2 — via cache manipulation:{' '}
+ onMutate snapshots the cache and writes the optimistic item
+ in. onError restores the snapshot on failure.
+
{lastError}
+ )} + +
+ Approach 1 — via UI variables: The pending item is
+ rendered directly from mutation.variables. No cache
+ manipulation needed. On error the pending item simply disappears.
+
+ {addTodoMutation.error.message} +
+ )} + +- In this example, new items can be created using a mutation. The new item - will be optimistically added to the list in hopes that the server - accepts the item. If it does, the list is refetched with the true items - from the list. Every now and then, the mutation may fail though. When - that happens, the previous list of items is restored and the list is - again refetched from the server. -
- -- In this example, new items can be created using a mutation. The new item - will be optimistically added to the list in hopes that the server - accepts the item. If it does, the list is refetched with the true items - from the list. Every now and then, the mutation may fail though. When - that happens, the previous list of items is restored and the list is - again refetched from the server. -
- -