获取查询后有条件地执行 graphql 突变

Posted

技术标签:

【中文标题】获取查询后有条件地执行 graphql 突变【英文标题】:Conditionally execute a graphql mutation after a query is fetched 【发布时间】:2021-01-18 03:10:15 【问题描述】:

场景

当用户通过身份验证时(isAuthenticated booelan ref):

    通过对后端的 graphql 调用检查用户是否有偏好 (useViewerQuery) 如果用户没有首选项,请设置默认值 (useSetPreferenceDefaultMutation)

问题

查询和突变在 graphql Playground 和 Vue 应用程序中都能正常工作。它们是使用graphql codegenerator 生成的,在后台使用useQuery 和useMutation。

我们遇到的问题是我们无法定义正确的顺序。有时useSetPreferenceDefaultMutationuseViewerQuery 之前执行。这会将用户的设置重置为默认值,而不是所需的行为。

此外,在页面刷新时一切正常。然而,当关闭一个重新打开的页面时,它总是调用useSetPreferenceDefaultMutation

代码

export default defineComponent(
  setup() 
    const 
      result: queryResult,
      loading: queryLoading,
      error: queryError,
     = useViewerQuery(() => (
      enabled: isAuthenticated.value,
    ))

    const 
      mutate: setDefaultPreferences,
      loading: mutationLoading,
      error: mutationError,
      called: mutationCalled,
     = useSetPreferenceDefaultMutation(
      variables: 
        language: 'en-us',
        darkMode: false,
      ,
    )

    onMounted(() => 
      watchEffect(() => 
        if (
          isAuthenticated.value &&
          !queryLoading.value &&
          !queryResult.value?.viewer?.preference &&
          !mutationCalled.value
        ) 
          void setDefaultPreferences()
        
      )
    )

    return 
      isAuthenticated,
      loading: queryLoading || mutationLoading,
      error: queryError || mutationError,
    
  ,
)

失败的努力

我们打开了一个问题 here 和 here,以便在 useQueryuseMutation 上有额外的选项,这可能对我们的场景有所帮助,但没有运气。 在watchEffect 上使用fetch 选项和syncpost 使用watch 代替watchEffect

【问题讨论】:

使用“跳过”选项 我相信 skip 与 Vue 中的 enabled 相同。在isAuthenticated 设置为true 后,查询正确执行,所以这不是问题。问题是突变有时会先执行。 在页面刷新时它按预期工作,但在关闭页面重新打开时它总是调用突变。这让我觉得if 子句中的条件是正确的。突变没有enabled 选项,它只在watchEffect 子句中使用setDefaultPreferences() 调用 只使用onCompleted ? 【参考方案1】:

感谢@xadm 的评论,它现在已通过在查询中使用onResult event hook 进行修复,因此它将在之后执行突变。

onResult(handler):当有新结果可用时调用事件挂钩。

export default defineComponent(
  setup(_,  root ) 
    const 
      loading: queryLoading,
      error: queryError,
      onResult: onQueryResult,
     = useViewerQuery(() => (
      enabled: isAuthenticated.value,
    ))

    const 
      mutate: setDefaultPreferences,
      loading: mutationLoading,
      error: mutationError,
     = useSetPreferenceDefaultMutation(
      variables: 
        language: 'en-us',
        darkMode: false,
      ,
    )

    onQueryResult((result) => 
      if (!result.data.viewer.preference) 
        void setDefaultPreferences()
      
    )

    return 
      isAuthenticated,
      loading: queryLoading || mutationLoading,
      error: queryError || mutationError,
    
  ,
)

【讨论】:

以上是关于获取查询后有条件地执行 graphql 突变的主要内容,如果未能解决你的问题,请参考以下文章

GraphQL 查询在突变后仅获取一次数据

GraphQL - 有条件地执行子查询

GraphQL - 有条件地执行子查询

突变查询 graphql-java

删除突变后不重新获取查询(Apollo Graphql & Nextjs)

当用户连续执行多个graphql突变时防止竞争条件