This is my memo from when I implemented optimistic updates with RTK Query.
Below is the final result of what I implemented. Both the “add to cart” and “add to wishlist” buttons send requests to the server to process these actions, the browser side acts like the client side manages these data.
We can leverage onQueryStarted to implement that feature. Here is an example of onQueryStarted usage.
async onQueryStarted({ cartItemToAdd }, { dispatch, queryFulfilled }) {
const patchResult = dispatch(
cartApi.util.updateQueryData("getCartItems", undefined, (draft) => {
const updatedCartItems = addItemToCart(
draft.cartItems,
cartItemToAdd
);
return {
...draft,
cartItems: updatedCartItems,
};
})
);
try {
await queryFulfilled;
} catch {
patchResult.undo();
}
Trouble shooting
Here are some mistakes I make made during the development process.
- Error: TypeError: Cannot read properties of undefined (reading 'select')
If you got this error message you might pass a wrong query name at updateQueryData.
In my case, I misspelled getCarItems.
// Correct
cartApi.util.updateQueryData("getCartItems", undefined, (draft) => {
const updatedCartItems = addItemToCart(
draft.cartItems,
cartItemToAdd
);
return {
...draft,
cartItems: updatedCartItems,
};
})
// Wrong
cartApi.util.updateQueryData("getCartItem", undefined, (draft) => {
const updatedCartItems = addItemToCart(
draft.cartItems,
cartItemToAdd
);
return {
...draft,
cartItems: updatedCartItems,
};
})
- Retune draft As long as I observe, it works without return when you directly modify the draft object like the example provided in the official document. Otherwise, you need to return the updated object.
// Works without return
async onQueryStarted({ wishlist }, { dispatch, queryFulfilled }) {
const patchResult = dispatch(
wishlistApi.util.updateQueryData(
"getWishlist",
undefined,
(draft) => {
draft.products = [...draft.products, wishlist];
}
)
);
try {
await queryFulfilled;
} catch {
patchResult.undo();
}
},
// Work only with return
cartApi.util.updateQueryData("getCartItems", undefined, (draft) => {
const updatedCartItems = addItemToCart(
draft.cartItems,
cartItemToAdd
);
return {
...draft,
cartItems: updatedCartItems,
};
})
ref:
https://redux-toolkit.js.org/rtk-query/usage/manual-cache-updates#optimistic-updates
original article is here
Top comments (0)