Apollo Client useLazyQuery making request 4-6 times

I am currently building a React Native application utilizing the Apollo Client to make requests to a Laravel-hosted GraphQL server. The issue that I am running into is that each query that I execute, regardless if I am using the useQuery or useLazyQuery hooks, is each request is hitting the server anywhere from 4-6 times. After reading various StackOverflow postings, I am aware that when in development, React will re-render a component twice to aid in debugging. This however does not justify the additional requests that my application is making. Overall, this issue does not appear to be affecting the mobile application at all, however with the additional requests being made, this is adding unnecessary stress to the server and inducing some rate limiting concerns.

Here are the versions that I am using:

@apollo/client: 3.9.9
react: 18.2.0
react-native: 0.73.2

Here is my query

const TODAY_QUERY: TypedDocumentNode<TodayResponse> = gql(/* GraphQL */ `
  query Today($date: String!) {
    today(datetime: $date) {
        interactions {
			id
			name
			interactionType {
				value
				display
			}
			date
			startTime
			endTime
			allDay
			connections {
				id
				firstName
				lastName
				avatar
			}
		}
		connections {
			id
			firstName
			lastName
			avatar
			followUp {
				display
				value
			}
			created
		}
    }
  }
`);

This is my client:

const client = new ApolloClient({
        uri: 'XXX',
        cache: new InMemoryCache(),
        headers: {
            Authorization: `Bearer ${session}`
        },
        queryDeduplication: true
    });

This is how the query is being executed:

const [initialLoading, setInitialLoading] = useState<boolean>(true)
const [getToday] = useLazyQuery(
    TODAY_QUERY,
    {
        variables: {
            date: moment().utc(false).format('YYYY-MM-DD HH:mm:ss')
        }
    }
)

useEffect(() => {
    getToday().then(response => {
        if (response.data) {
            parseTodayResponse(response.data)
        } else {
            console.error(response.error);
        }
        setShowInteractionNotification(false)
    }).catch(error => {
        console.error(error)
    })
}, [])

This is your problem - your variables are constantly changing around, so Apollo Client sees them as different queries and will not be able to deduplicate them any any way.

That said, you really shouldn’t call a lazyQuery execution function in useEffect - just use useQuery instead.

You could initialize your date in local state:

const [date, setDate] = useState(moment().utc(false).format('YYYY-MM-DD HH:mm:ss'))
const { data } = useQuery(
    TODAY_QUERY,
    {
        variables: {
            date: date
        }
    }
)
1 Like

That appears to have fixed the duplicate request issue, thank you very much.

Regarding the point that you made about using calling useLazyQuery query within the useEffect hook, the reason I constructed it this way was to allow for the user to “pull-to-refresh” within the ListView, and thus not requiring me to build multiple queries. To be honest, I have never used the refetch method within the client. How would I go about performing a refetch when the user wants to refresh their content?

Well, you just call hookReturnValue.refetch()?

1 Like

Ok thanks. This is what I ended up with that appears to be working flawlessly:

const { refetch: refreshToday } = useQuery(
        TODAY_QUERY,
        {
            variables: {
                date: currentDate
            },
            onCompleted: (data: TodayResponse) => {
                parseTodayResponse(data)
                setShowInteractionNotification(false)
            },
            onError: (error) => {
                setShowInteractionNotification(false)
            }
        },
    )

const onRefresh = useCallback(async () => {
        setRefreshing(true);
        await refreshToday()
        setRefreshing(false);
    }, [refreshToday]);