Nuxt3 Apollo中Mutation完成后Fetch请求未发送的原因
问题分析与解决方案
问题描述
在Nuxt3应用中使用Apollo发送添加产品的Mutation后,在onDone回调中调用fetchProducts函数期望获取最新数据,但函数执行后无新网络请求,页面仍显示旧数据。代码如下:
<script setup> const myProducts = ref([]); const addNewProductData= ref({id:1,name:'test'}); const isLoading = ref(false); const total=ref(1); const getAllQuery = gql` query fetchProducts{ FetchProductPagination( page:1, limit:10, ){ total data{ id name } } } `; const fetchProducts = async () => { isLoading.value = true; const { data, error } = await useAsyncQuery(getAllQuery, null, "product"); if (data.value) { myProducts.value = data.value.FetchProductPagination.data; total.value = data.value.FetchProductPagination.total; } isLoading.value = false; }; const onSubmitAddProduct= async () => { const query = gql` mutation AddProduct{ AddProduct( id:${JSON.stringify(addNewProductData.id)}, name: ${JSON.stringify(addNewProductData.name)} ) { id name } } `; const { mutate, onDone } = await useMutation(query, { clientId: "product" }); mutate(); onDone(() => { fetchProducts() }); }; </script> <template> <button @click="onSubmitAddProduct">add</button> </template>
核心原因
- useAsyncQuery缓存机制:Nuxt Apollo的
useAsyncQuery默认启用缓存,当相同查询(查询语句+变量完全一致)再次执行时,会直接返回缓存中的旧数据,不会发起新网络请求。 - Mutation写法不规范:直接通过模板字符串拼接变量,不仅存在GraphQL注入风险,而且由于
addNewProductData是ref对象,直接访问addNewProductData.id并未获取响应式的最新值(本例中为固定值,但写法逻辑错误)。
修复方案
方案一:强制刷新查询(禁用缓存)
修改fetchProducts函数,给useAsyncQuery添加fetchPolicy参数,强制从网络获取最新数据:
const fetchProducts = async () => { isLoading.value = true; // 添加fetchPolicy: 'network-only' 强制跳过缓存,发起新请求 const { data, error } = await useAsyncQuery(getAllQuery, null, { clientId: "product", fetchPolicy: 'network-only' }); if (data.value) { myProducts.value = data.value.FetchProductPagination.data; total.value = data.value.FetchProductPagination.total; } isLoading.value = false; };
方案二:规范Mutation写法+缓存更新(更高效)
不依赖重新查询,而是在Mutation完成后直接更新Apollo缓存和本地状态,避免额外网络请求:
const onSubmitAddProduct = async () => { // 使用变量定义Mutation,避免字符串拼接 const addProductMutation = gql` mutation AddProduct($id: ID!, $name: String!) { AddProduct(id: $id, name: $name) { id name } } `; const { mutate } = await useMutation(addProductMutation, { clientId: "product", // 直接更新缓存 update(cache, { data: { AddProduct } }) { // 读取缓存中已有的产品列表 const existingData = cache.readQuery({ query: getAllQuery }); if (existingData) { // 更新缓存数据 cache.writeQuery({ query: getAllQuery, data: { FetchProductPagination: { ...existingData.FetchProductPagination, data: [...existingData.FetchProductPagination.data, AddProduct], total: existingData.FetchProductPagination.total + 1 } } }); // 同步更新本地响应式变量,无需重新查询 myProducts.value = [...myProducts.value, AddProduct]; total.value += 1; } } }); // 传入变量时需访问ref的value属性 mutate({ id: addNewProductData.value.id, name: addNewProductData.value.name }); };
这种方式无需调用fetchProducts,直接通过Apollo的缓存更新机制同步数据,性能更优。
内容的提问来源于stack exchange,提问作者Mohammad
相关产品推荐
相关产品推荐

