Apollo Hooks - useLazyQuery not using onCompleted option if passed on query
Asked Answered
A

3

10

I have a custom debounce hook for apollo lazy queries:

import {useLazyQuery} from '@apollo/react-hooks';
import debounce from "lodash/debounce";

export function useDebouncedQuery(schema) {
    const [doQuery, {...rest}] = useLazyQuery(schema);

    const query = React.useCallback(debounce(doQuery, 1000), []);

    return [query, {
        ...rest
    }]
}

This works, other than the onCompleted option. When implementing the hook like this:

const [doQuery] = useDebouncedQuery(query);
doQuery({
    onCompleted: data => {
        console.log(data);
    }
})

...the onCompleted option doesn't fire. But, if I change the hook to be:

export function useAsyncSelectQuery(schema, options) {
    const [doQuery, {...rest}] = _useLazyQuery(schema, options);
    ...

.. and implement it like this, it works:

const [doQuery] = useDebouncedQuery(query, {
    onCompleted: data => {
        console.log(data);
    }
});

Why is this? Am I doing something wrong? I have separate logic that needs to handle the data passed to onCompleted in different places so I can't pass that option when the query gets initialized. Any help is greatly appreciated.

Anglicism answered 9/8, 2019 at 16:55 Comment(0)
W
7

So, the function returned by the useLazyQuery hook doesn't have an onCompleted property on the options parameter, so you can't use it.

According to the docs: https://www.apollographql.com/docs/react/api/react-hooks/#result-1, the function returns a QueryLazyOptions, these are the params:

export interface QueryLazyOptions<TVariables> {
    variables?: TVariables;
    context?: Context;
}

I think a good solution to the task you're trying to achieve is to use an useEffect hook, to watch for changes in the property data returned by the useDebouncedQuery hook and then handle the data as you want to.

Code below:

const [doQuery, { data, loading, error }] = useDebouncedQuery(
  QUERY
);

useEffect(() => {
  if (data && data.property && !loading) {
    // handle data here
  }
}, [data, loading]);

function handleQuery() {
  doQuery();
}

Hope this help!

Wolff answered 5/9, 2019 at 16:41 Comment(0)
M
3

You can't set onCompleted when you're calling useLazyQuery, but you can when you're defining useLazyQuery.

So this will not work:

const [doQuery] = useDebouncedQuery(query);
doQuery({
    onCompleted: data => {
        console.log(data);
    }
})

But this will work:

const [doQuery] = useDebouncedQuery(query, {
    onCompleted: data => {
        console.log(data);
    }
});
doQuery()

Note:

Execute function (first tuple item): Function that can be triggered to execute the suspended query. After being called, useLazyQuery behaves just like useQuery. The useLazyQuery function returns a promise that fulfills with a query result when the query succeeds or fails.

So when you call the excute function doQuery it'll behave like doing the thing and if it success, it'll go and call the onCompleted function declared in the useLazyQuery.

Marra answered 11/10, 2021 at 11:38 Comment(0)
M
-3

Pass the onCompleted function when you init the useLazyQuery

const [doQuery] = useDebouncedQuery(query, {
    onCompleted: data => {
        console.log(data);
    }
});

doQuery()
Mons answered 24/8, 2020 at 11:45 Comment(1)
onCompleted doesn't exist on useLazyQueryFitzhugh

© 2022 - 2024 — McMap. All rights reserved.