'How to trigger graphql useQuery on demand only once?
With the help of graphql-codegenerator we created a graphql useQuery
that correctly retrieves data from the backend. When a string is entered into an input field the function driverRule
is called to verify the input, which in turn should call the useQuery
only once.
Problem
However, when we enable
the query with the ref
useQuery is immediately executed, a second execution is invoked with the refetch()
method. All subsequent calls to driverRule
will only invoke useQuery once as desired. But the very first call does it twice which is not desired.
import {computed, defineComponent, ref } from '@vue/composition-api'
import { useSapTruckRosterDriverQuery } from 'src/graphql/generated/operations'
export default defineComponent({
setup(_, { emit }) {
const showTruckId = ref(false)
const driverId = computed(() => (!showTruckId.value ? answer.value : ''))
const queryEnabled = ref<'driver' | 'truck'>()
const { refetch: getDriverQuery } = useSapTruckRosterDriverQuery(
() => ({ id: driverId.value }),
() => ({ enabled: queryEnabled.value === 'driver' })
)
const driverRule = async (value: string) => {
queryEnabled.value = 'driver'
const result = await getDriverQuery({ id: value })
if (result.data.driver.__typename === 'DriverArray') {
return result.data.driver.data?.length ? true : 'Truck not found'
}
}
What we tried:
- Move
useQuery
within thedriverRule
function but this yields the following error:
[Vue warn]: onServerPrefetch is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup().
- useQuery with option
emabled: false
and onlyrefetch()
indriverRule
. This does not execute useQuery at all
Workaround
Accept the default behavior and enable the query by default with a static variable value and not use the result from the first run but only the one from refetch()
. This still results in 2 calls to the backend though, but it can't be avoided.
const { refetch: getDriverQuery } = useSapTruckRosterDriverQuery(
{ id: 'initialQueryActivationCall' }
)
const driverRule = async (value: string) => {
const result = await getDriverQuery({ id: value })
if (result.data.driver.__typename === 'DriverArray') {
return result.data.driver.data?.length ? true : 'Truck not found'
}
}
Question
It seems really hard to just call useQuery
only once when the function driverRule
is called. How can we avoid having 2 calls when only 1 call is needed to the backend?
Solution 1:[1]
You can use useApolloClient from @vue/apollo-composable package.
//other imports...
import { useApolloClient } from '@vue/apollo-composable'
import { gql } from '@apollo/client/core'
export default defineComponent({
setup() {
const { client } = useApolloClient()
const GET_DOGS = gql`
query GetDogs {
dogs {
id
breed
}
}
`;
const getDogs = async (): Promise<void> => {
const { data, } = await client.query({
query: GET_DOGS
})
}
return {
getDogs,
}
},
})
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | JanuszO |