初學者指南:完整解析 useMutation 的參數與用法
更新日期: 2025 年 6 月 10 日
GraphQL 是現代前端開發中非常熱門的 API 技術,而在 React 應用中,Apollo Client 是最常使用的 GraphQL 工具。
當你需要「新增 / 更新 / 刪除」資料時,useMutation
是我們的主要利器。
但除了發送請求之外,useMutation
其實還能透過「第二個參數:設定物件(options object)」做更多事,包括:
- 傳入變數
- 成功或失敗時要執行的 callback
- 快取更新
- 實作樂觀 UI
- 設定 headers
- 等待 refetch 完成
這篇文章將帶你完整理解 useMutation
的參數用法,從基本到進階,適合 Apollo Client 新手或希望進一步掌握 GraphQL 實務技巧的開發者。
useMutation
是什麼?
在 Apollo Client 中,useMutation
是一個專門用來發送 GraphQL mutation 請求 的 React Hook。
在 GraphQL 中,「mutation」指的是對伺服器資料的寫入操作,像是:
- 新增文章
- 更新使用者資訊
- 刪除留言
而 useMutation
就是用來幫我們完成這些操作的工具。
為什麼用 Hook?
React 中的 Hook 是一種讓我們在函式型元件中使用 state 與副作用的機制。
Apollo Client 將 mutation 封裝成 Hook,原因有三:
- 符合 React 思維:使用
useMutation
可以讓資料邏輯緊貼 UI 元件。 - 內建狀態管理:它會自動提供 loading、error、data 等狀態值,讓你能根據請求狀況更新畫面。
- 整合 Apollo 快取邏輯:可以搭配 options object 操作快取、錯誤處理與 refetch 等行為。
基本語法結構
const [createPost, { data, loading, error }] = useMutation(CREATE_POST);
拆解說明如下:
createPost
:觸發函式,當你要發送 mutation 時就執行它(通常在onClick
或onSubmit
中呼叫)CREATE_POST
:一段 GraphQL 的 mutation 語法(通常用 gql 標記寫成常數)data
:請求成功後的回傳資料loading
:布林值,表示請求是否還在進行中error
:如果發生錯誤,這裡會帶有錯誤資訊
範例:
const [createPost, { data, loading, error }] = useMutation(CREATE_POST);
const handleSubmit = () => {
createPost({
variables: {
title: '我的第一篇文章',
content: '這是一段測試內容'
}
});
};
認識第二個參數:設定物件(Options Object)
useMutation
可以接受第二個參數,也就是本文的重點 —— 「設定物件(options object)」。
這個物件用來「設定 mutation 的額外行為」,例如:
- 要傳哪些變數(
variables
) - 成功或失敗時該怎麼處理(
onCompleted
、onError
) - 快取要怎麼更新(
update
、refetchQueries
) - 要不要顯示假資料做出樂觀 UI 效果(
optimisticResponse
) - 要不要傳自訂 header(
context
)
實際語法範例
const [createPost] = useMutation(CREATE_POST, {
variables: {
title: 'Hello World',
content: '這是一篇文章'
},
onCompleted(data) {
console.log('新增成功!', data);
},
onError(error) {
console.error('新增失敗:', error.message);
}
});
這段程式碼等同於:
- 幫你送出 GraphQL mutation 請求
- 傳入 mutation 所需的參數
- 成功時印出回傳結果
- 失敗時顯示錯誤訊息
注意事項
這個設定物件(第二個參數)只能寫 Apollo Client 預定義的 key,像是:
variables
onCompleted
onError
refetchQueries
update
context
optimisticResponse
awaitRefetchQueries
如果你寫了像這樣的 key:
useMutation(CREATE_POST, {
foo: 'bar' // ❌ 錯誤!Apollo 不認得這個設定
});
- JavaScript 會忽略它
- TypeScript 會直接報錯(這也是 TypeScript 的好處)
常用參數介紹
Apollo Client 的 useMutation
支援多種參數,讓你可以更靈活控制整個請求的行為,包括資料傳入、成功與錯誤的後續處理、快取更新等。
以下為常見設定項目,將搭配背景說明與範例幫助你理解每個參數的實際用法。
variables
:傳入 GraphQL 所需的變數
用途:提供給 mutation 執行所需的參數,對應你在 GraphQL 文件中定義的 $變數名稱
。
背景說明:GraphQL mutation 支援變數機制,能讓請求更彈性、更容易重複使用,並避免硬編碼。Apollo 建議將變數透過 variables
屬性傳入,而非直接寫死在 gql
語法中。
範例:
const [createPost] = useMutation(CREATE_POST, {
variables: {
title: '我的第一篇文章',
content: '內容內容內容'
}
});
✅ 提示:
variables
的 key 必須對應到你 GraphQL 中定義的變數名稱。- 如果變數是可選的(例如
$subtitle: String
),你可以選擇不傳。
onCompleted
:成功時的 callback
用途:當 mutation 成功執行、收到伺服器回傳資料後,自動觸發此函式。
常見情境:
- 顯示成功訊息(如 toast)
- 導頁至其他畫面(如跳回列表)
- 清空表單
範例:
const [createPost] = useMutation(CREATE_POST, {
onCompleted(data) {
alert(`成功新增文章:${data.createPost.title}`);
}
});
✅ 提示:
- 回傳值會透過
data
傳入函式中,你可以自由使用裡面的資料。 - 若 mutation 沒有回傳任何欄位,
data
會是undefined
。
onError
:錯誤時的 callback
用途:當 mutation 發生錯誤(例如伺服器錯誤、驗證失敗、網路錯誤等),會觸發這個函式。
常見用途:
- 顯示錯誤訊息
- 將錯誤記錄下來(例如送至錯誤追蹤服務)
- 高亮表單錯誤欄位
範例:
const [createPost] = useMutation(CREATE_POST, {
onError(error) {
console.error('新增失敗:', error.message);
}
});
✅ 提示:
error
物件是 Apollo Client 的 GraphQL error 實例,可透過.message
、.graphQLErrors
、.networkError
存取詳細錯誤原因。- 可搭配
errorPolicy
調整錯誤處理邏輯(預設為 “none”)。
refetchQueries
:成功後重新查詢特定 Query
用途:當 mutation 執行成功後,重新發送一個或多個 Query 來同步更新畫面資料。
背景說明:某些情況下,手動更新快取太麻煩或難以維護,可以直接透過這個選項自動重新查詢。
範例:
const [createPost] = useMutation(CREATE_POST, {
refetchQueries: [{ query: GET_POSTS }]
});
✅ 提示:
- 支援多個查詢(以陣列表示)。
- 也可加上變數:
{ query: GET_POSTS, variables: { category: 'news' } }
。 - 預設不會等 refetch 完成就結束 mutation(需搭配
awaitRefetchQueries
)。
⚠️ 缺點:會額外發出網路請求,對效能有些影響。
update
:手動操作 Apollo 快取
用途:當 mutation 成功後,你可以直接操作 Apollo 的快取內容,讓畫面同步更新而不必重新查詢。
背景說明:這是控制效能與自訂畫面更新的進階功能。
範例:
const [createPost] = useMutation(CREATE_POST, {
update(cache, { data }) {
const newPost = data.createPost;
const existing = cache.readQuery({ query: GET_POSTS });
cache.writeQuery({
query: GET_POSTS,
data: {
posts: [newPost, ...existing.posts]
}
});
}
});
✅ 提示:
cache.readQuery
和cache.writeQuery
是操作快取的基本方式。- 快取資料結構必須和 query 對應完全一致。
- 若 mutation 回傳資料太少,這邊可能無法更新完整快取。
optimisticResponse
:先顯示預期結果,打造樂觀 UI
用途:在伺服器還沒真正回應之前,預先在畫面上顯示「假資料」,達到 UI 即時回應的效果。
常見情境:
- 點讚按鈕馬上加一
- 新增留言立即顯示
- 刪除項目立即從列表消失
範例:
const [createComment] = useMutation(CREATE_COMMENT, {
optimisticResponse: {
createComment: {
id: 'temp-id',
content: '我先顯示了',
__typename: 'Comment'
}
}
});
✅ 提示:
__typename
是必需的,否則 Apollo Cache 可能無法辨識這筆資料。- 這筆「假資料」會在真正回應後被替換,若失敗則會自動復原。
context
:傳遞額外資訊(如認證 Header)
用途:給中介層(如 Apollo Link、middleware)傳遞額外資訊,例如認證用的 token。
範例:
const [deletePost] = useMutation(DELETE_POST, {
context: {
headers: {
authorization: `Bearer ${token}`
}
}
});
✅ 提示:
- 此 context 僅作用於這次的 mutation 請求。
- 若你已經在 Apollo Client 的
setContext
裡統一處理授權,一般不需要每次手動設。
awaitRefetchQueries
:等待 refetch 查詢完成後再結束 mutation
用途:讓 mutation 等待 refetchQueries
完成後才結束流程,適用於需要在 refetch 後再做後續操作的場景。
範例:
const [createPost] = useMutation(CREATE_POST, {
refetchQueries: [{ query: GET_POSTS }],
awaitRefetchQueries: true
});
✅ 提示:
- 這會讓 mutation 的 Promise 等 refetch 完成後才 resolve。
- 適合用於有「下一步」依賴 refetch 結果的流程,例如頁面跳轉、顯示 loading spinner 等。
以上就是 useMutation
中最常見的設定項目介紹。
每個參數都有它的使用情境與搭配時機,建議初學者可以先熟悉基本參數如 variables
、onCompleted
、onError
,再逐步學習 update
、optimisticResponse
等進階功能。
結語
useMutation
的第二個參數(設定物件)是 GraphQL 請求中非常強大的一環。熟悉它能幫你:
- 提升使用者體驗
- 優化效能與快取邏輯
- 管理請求流程與錯誤處理
當你學會善用這些參數,你的 GraphQL 實作將更靈活、穩定、好維護。