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

useMutation配置refetchQueries时关联useQuery的onCompleted不触发如何解决?

问题原因

Apollo Client的useQuery的onCompleted回调默认仅在首次主动查询成功完成时触发,通过refetchQueries、refetch方法触发的重取操作、缓存更新触发的查询数据更新,都不会触发该回调,这是官方的预设行为。
另外你当前refetchQueries仅传查询名称字符串的写法也可能存在匹配问题:如果对应useQuery的变量和重取时传入的变量不一致,Apollo Client会创建新的查询实例,不会关联到你已经声明的那个useQuery,自然也不会触发对应回调。

解决方案
  • 方案1:将逻辑迁移到useEffect监听数据变化
    把原本写在onCompleted里的逻辑,改为监听useQuery返回的data和loading状态,只要数据更新就执行对应逻辑:
let { loading, data } = useQuery(
  gql`
    ${templateFragment}
    query getUserData($userToken: String) {
      getUsersData(userToken: $userToken) {
        templates {
          ...template
        }
        token
      }
    }
  `,
  {
    variables: {
      userToken: userToken ? userToken.replace(/"/g, ``) : null,
    },
    onError: () => console.log("err"),
  }
);

useEffect(() => {
  // 加载结束且数据存在时执行逻辑
  if (!loading && data?.getUsersData) {
    props.isAuthAC(
      true,
      data.getUsersData.templates,
      data.getUsersData.token
    );
  }
}, [loading, data, props]);
  • 方案2:修改refetchQueries写法,指定完整查询和变量,同时配置awaitRefetchQueries
    如果需要在mutation完成、所有重取查询结束后执行逻辑,可以直接在mutation的回调里处理,不用依赖useQuery的onCompleted:
    首先把你的查询单独抽出来复用:
// 单独抽离gql查询定义方便复用
const GET_USER_DATA = gql`
  ${templateFragment}
  query getUserData($userToken: String) {
    getUsersData(userToken: $userToken) {
      templates {
        ...template
      }
      token
    }
  }
`

修改useMutation配置:

let [saveTemplate, { loading}] = useMutation(gql`
  ${templateFragment}
  mutation saveTemplate ($template:saveTemplateTemplatesType!,$token:String!){
    saveTemplate(template:$template,token:$token){
    ...template
    }
  }
  `,{
    refetchQueries: [
      {
        query: GET_USER_DATA,
        // 传入和useQuery完全一致的变量
        variables: { userToken: userToken ? userToken.replace(/"/g, ``) : null }
      }
    ],
    // 等待所有重取查询完成后再触发onCompleted
    awaitRefetchQueries: true,
    onError:()=>{message.warn("error")},
    onCompleted:()=>{
      console.log("success")
      // 这里可以直接从缓存读取最新数据执行逻辑,也可以通过client.readQuery读取最新的getUserData数据
    }
});
  • 方案3:直接通过mutation返回结果更新缓存(最优性能)
    如果mutation返回的结果已经包含了更新后的模板数据,你可以直接在onCompleted里手动更新Apollo缓存里的getUserData数据,不需要额外发起重取请求,性能更好。

内容的提问来源于stack exchange,提问作者derty14

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 02:36:04