Có ba cách để cập nhật cache một cách thủ công sau khi gửi một mutation request.
- Optimistic: cập nhật khi mutation request vừa được gửi và không chờ để nhận response.
- Pessimistic: cập nhật sau khi nhận response.
- General: cập nhật ở trong component thay vì ở trong API slice.
Ta chỉ quan tâm đến hai cách đầu tiên.
Optimistic
Đầu tiên, khai báo thuộc tính onQueryStarted bên trong object truyền vào phương thức mutation của endpoint.
updateSneaker: builder.mutation({
onQueryStarted: async (arg, api) => {
// ...
},
})Thuộc tính này là một callback với đối số đầu tiên là đối số truyền vào hook và đối số thứ hai là các API chẳng hạn như dispatch hay queryFulfilled.
Ví dụ:
updateSneaker: builder.mutation({
onQueryStarted: async ({ productId, ...patch }, { dispatch, queryFulfilled }) => {
// ...
},
})Callback của onQueryStarted sẽ được thực thi khi request vừa được gửi đi.
Để cập nhật cache một cách thủ công, ta gọi sử dụng phương thức updateQueryData như sau:
onQueryStarted: async ({ productId, ...patch }, { dispatch, queryFulfilled }) => {
const patchResult = dispatch(
sneakerApi.util.updateQueryData("getSneakerById", productId, (draft) => {
Object.assign(draft, patch)
}),
)
}Đối số của updateQueryData bao gồm:
- Tên query endpoint mà ta muốn gọi sử dụng để cập nhật cache (
"getSneakerById"). - Đối số truyền vào query (
productId). - Callback giúp cập nhật cache, hoạt động dựa trên Immer.
Giá trị trả về của updateQueryData là một thunk action nên ta có thể dispatch nó như một action thông thường.
Để xử lý lỗi, ta dùng promise queryFulfilled như sau:
onQueryStarted: async ({ productId, ...patch }, { dispatch, queryFulfilled }) => {
const patchResult =
dispatch()
// ...
try {
await queryFulfilled
} catch {
patchResult.undo()
}
}Trong trường hợp queryFulfilled quăng ra lỗi, ta có thể dùng phương thức undo từ patchResult để undo lại những update đã diễn ra.
Chúng ta cũng có thể viết gọn đoạn code trên lại như sau:
onQueryStarted: async ({ productId, ...patch }, { dispatch, queryFulfilled }) => {
const patchResult =
dispatch()
// ...
queryFulfilled.catch(patchResult.undo())
}Pessimistic
Tương tự với optimistic update, ta cũng dùng thuộc tính onQueryStarted và promise queryFulfilled. Hai cách cập nhật này chỉ khác nhau ở thứ tự gọi sử dụng promise.
onQueryStarted: async ({ productId }, { dispatch, queryFulfilled }) => {
try {
const { data: updatedSneaker } = await queryFulfilled
dispatch(
sneakerApi.util.updateQueryData("getSneakerById", productId, (draft) => {
Object.assign(draft, updatedSneaker)
}),
)
} catch {}
}Có thể thấy, ta chờ promise queryFulfilled resolve xong rồi mới tiến hành cập nhật cache.
Attention
Nếu sử dụng thêm thuộc tính
invalidatesTagsđể triển khai việc cập nhật cache tự động thì cơ chế cập nhật cache thủ công có thể không hoạt động.