Условно выполнить мутацию graphql после получения запроса

Сценарий

Когда пользователь аутентифицирован (isAuthenticated логическая ссылка):

  1. Проверьте, есть ли у пользователя предпочтения, обратившись к бэкенду graphql (useViewerQuery)
  2. Если для пользователя нет предпочтений, установите значение по умолчанию (useSetPreferenceDefaultMutation)

Проблема

И запрос, и мутация корректно работают на игровой площадке graphql и в приложении Vue. Они были сгенерированы с помощью генератора кода graphql, который использует useQuery и useMutation в фоновом режиме.

Проблема в том, что мы не можем определить правильный порядок. Иногда useSetPreferenceDefaultMutation выполняется раньше useViewerQuery. Это сбрасывает настройки пользователя на значения по умолчанию, и это не является желаемым поведением.

Кроме того, при обновлении страницы все работает правильно. Однако при закрытии повторного открытия страницы он всегда вызывает 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,
    }
  },
})

Неудачные попытки

  • Мы открыли задачу здесь и здесь, чтобы иметь дополнительные параметры для useQuery или useMutation, которые могли бы помочь в нашем сценарии, но не повезло.
  • Используйте вариант fetch с sync или post на watchEffect
  • Используйте watch вместо watchEffect

person DarkLite1    schedule 02.10.2020    source источник
comment
использовать опцию «пропустить»   -  person xadm    schedule 02.10.2020
comment
Я полагаю, что skip такой же, как enabled во Vue. Запрос выполняется правильно после того, как isAuthenticated установлено в true, так что это не проблема. Проблема в том, что мутация иногда выполняется первой.   -  person DarkLite1    schedule 02.10.2020
comment
При обновлении страницы он работает по назначению, но при закрытии страницы и повторном открытии он всегда вызывает мутацию. Это заставляет меня думать, что условия в предложении if верны. В мутации нет опции enabled, она вызывается только в предложении watchEffect с setDefaultPreferences()   -  person DarkLite1    schedule 02.10.2020
comment
просто используйте onCompleted ?   -  person xadm    schedule 02.10.2020


Ответы (1)


Благодаря комментарию @xadm теперь это исправлено с помощью перехватчика событий onResult в запросе, поэтому впоследствии он выполнит мутацию.

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,
    }
  },
})
person DarkLite1    schedule 02.10.2020