Để thực hiện gửi request thay đổi dữ liệu (mutation request) đến API bằng RTK Query, ta cần:

  • Định nghĩa các mutation endpoint khi tạo ra API slice.
  • Gọi sử dụng hook của API slice để lấy ra hàm giúp gửi mutation request và kết quả trả về của request.

Defining Mutation Endpoints

Các mutation endpoint của một API slice được định nghĩa thông qua phương thức builder.mutation:

endpoints: (builder) => ({
  endpoint: builder.mutation({
    // ...
  }),
})

Phương thức này cũng nhận vào một object gồm nhiều thuộc tính tương tự với builder.query (xem thêm Defining Query Endpoints).

Tuy nhiên, giá trị trả về của thuộc tính query cần phải là một object bao gồm URL của endpoint, phương thức của request và request body.

query: ({ productId, ...sneaker }) => ({
  url: `products/${productId}`,
  method: "PUT",
  body: sneaker,
})

Performing Mutations with React Hooks

Ta gọi tất cả các hook tương ứng với các mutation endpoint ở trong các API slice là useMutation.

Mutation Hook Behavior

Khác với hook useQuery của query endpoint (xem thêm Performing Queries with React Hooks), hook useMutation có giá trị trả về là một tuple.

  • Phần tử đầu tiên là một trigger function giúp gửi mutation request (mutation trigger).
  • Phần tử thứ hai là một object chứa dữ liệu của response (status, errordata).

Ví dụ:

const [updateSneaker, { isLoading: isUpdating }] = useUpdateSneakerMutation()

Không giống như useQuery, hook useMutation không thực thi một cách tự động. Để gửi mutation request, ta cần gọi thực thi mutation trigger một cách tường minh:

function handleClick() {
  updateSneaker({ ...sneaker, price: parseInt(newPrice, 10) })
}

Đối số của hàm updataSneaker (mutation trigger) sẽ được truyền cho callback của mutation endpoint.

Frequently Used Mutation Hook Return Values

Một số thuộc tính thường dùng có trong mutation result:

  • data: lưu dữ liệu trả về.
  • error: lỗi của mutation request.
  • isLoading: cho biết mutation request đã được gửi và đang chờ phản hồi.

Mutation request không phân biệt giữa “loading” và “fetching” do không có khái niệm “re-fetching”. Chỉ có “loading” và “not loading”.

Ví dụ sử dụng mutation endpoint kết hợp với query endpoint:

function Sneaker() {
  const { data: sneaker, isLoading } = useGetSneakerByIdQuery("product_gs75q9f5al")
  const [updateSneaker, { isLoading: isUpdating }] = useUpdateSneakerMutation()
 
  function handleClick() {
    updateSneaker({ ...sneaker, price: Math.floor(Math.random() * 200) })
  }
 
  if (isLoading) return <h3>"Loading..."</h3>
  return (
    <div>
      <h3>{sneaker.name}</h3>
      <p>${sneaker.price}</p>
      <button onClick={handleClick} disabled={isUpdating}>
        Update to a random price
      </button>
    </div>
  )
}

Trong component trên, khi ta bấm vào nút “Update to a random price” thì mutation trigger updateSneaker sẽ được gọi để gửi đi mutation request. Trong thời gian mutation request đang được xử lý, biến boolean isUpdating sẽ có giá trị là true và do đó mà nút bấm sẽ bị disable.

Resources