You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 13:07:42