# Optimistic Updates and Polling — Redux Toolkit / Zustand

Source: https://www.skillbyai.com/en/redux-zustand/q-optimistic

> Fast UIs and fresh data.

## Patch the cache, undo on failure

For instant feedback, a mutation's `onQueryStarted(arg, { dispatch, queryFulfilled })` can patch cached data with `api.util.updateQueryData(endpoint, args, draft => ...)`, which returns a patch result. If `await queryFulfilled` throws, call `patchResult.undo()` to roll back. For data that changes on the server without user action, pass `{ pollingInterval: ms }` to a query hook; other options include `refetchOnFocus` and `refetchOnReconnect` (which need `setupListeners(store.dispatch)`) and `skip` to delay a query until its argument is ready.

## Optimistic like and polling

An endpoint and its usage.

```tsx
likePost: builder.mutation<void, number>({
  query: (id) => ({ url: `posts/${id}/like`, method: 'POST' }),
  async onQueryStarted(id, { dispatch, queryFulfilled }) {
    const patch = dispatch(
      api.util.updateQueryData('getPost', id, (draft) => {
        draft.likes += 1; // assumes Post has a likes: number field
      })
    );
    try {
      await queryFulfilled;
    } catch {
      patch.undo(); // roll back if the server rejected it
    }
  },
}),

// component: refresh every 30 seconds while mounted
const { data } = useGetPostQuery(id, { pollingInterval: 30_000, skip: !id });
```

## Pessimistic is fine too

Optimistic updates add complexity. For actions that often fail or where correctness matters more than speed (payments), wait for the server and then update or invalidate.

**Quiz:** How do you roll back an optimistic cache patch when the request fails?

- [ ] Reload the page
- [x] Call undo() on the patch result returned by dispatching updateQueryData
- [ ] Dispatch api.util.resetApiState() always
- [ ] Throw from the reducer

*Answer:* Call undo() on the patch result returned by dispatching updateQueryData. The patch result knows how to reverse itself.
