DEV Community

Cover image for Optimistic Updates with RTK Query
Yuko
Yuko

Posted on

Optimistic Updates with RTK Query

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();
    }
Enter fullscreen mode Exit fullscreen mode

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,
                };
              })
Enter fullscreen mode Exit fullscreen mode
  • 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();
            }
          },
Enter fullscreen mode Exit fullscreen mode
    // Work only with return
    cartApi.util.updateQueryData("getCartItems", undefined, (draft) => {
                const updatedCartItems = addItemToCart(
                  draft.cartItems,
                  cartItemToAdd
                );
                return {
                  ...draft,
                  cartItems: updatedCartItems,
                };
    })
Enter fullscreen mode Exit fullscreen mode

ref:

https://redux-toolkit.js.org/rtk-query/usage/manual-cache-updates#optimistic-updates

original article is here

Top comments (0)