useLazyQuery not working inside loop and promise.all

Viewed 1292

I've got an array of data(consist of date), and need to run a graphql query for every date inside it. Promise resolved for every date inside the array should return new data and I want to push it in the local state of react component.

But somehow, the function is only returning data for the last element of an array.

    ...
    const [
        getInvoiceByDateQuery,
        { loading: getInvoiceByDateQueryLoading, data: getInvoiceByDateQueryData },
      ] = useLazyQuery(GET_INVOICES_BY_DATA, {
        onCompleted({ getInvoicesByDate }) {
          console.log({ getInvoicesByDate });
          const invoiceList = [...state.invoiceList];
          invoiceList.push(getInvoicesByDate[0]);
          _setState({
            invoiceList,
          });
        },
      });
    
    ...
    
    useEffect(async () => {
    if (!!state.currentWeek.length) {
      await Promise.all(
        state.currentWeek.map(day => {
          console.log(day);
          return getInvoiceByDateQuery({
            variables: {
              date: day,
            },
          });
        }),
      );
    }
  }, []);

I went through graphql documentation, it says useLazyQuery doesn’t return any promise like useMutation too. So, inside my useEffect hook Promise.all is always going to return void.

I'm hoping to use onCompleted return callback of useLazyQuery and update the local state.

I tried using console inside map iterator, it's printing the date in console successfully for every element inside array but somehow function is only running for the last element.

Even checking the networks tab, I see the query runs only a single time.

I tried the following code too, but nothing is working -

useEffect(() => {
    if (!!state.currentWeek.length) {
      state.currentWeek.map(day =>
        getInvoiceByDateQuery({
          variables: {
            date: day,
          },
        }),
      );
    }
  }, []);
2 Answers

Every Apollo hook creates one 'instance', were designed to provide one operation ('data-slots') at a time.

... should return new data and I want to push it in the local state of react component.

Usually [and probably in this use case, too] there is no need to copy data into the state (data duplication).

In React you should think about many <Day/> components, each reading data for itself, rendering day-related data, providing a link to day-details page/view/etc.

Of course, each <Day/> component can return fetched data to the parent, simply render it with some handler fn (and id/index props) called in onCompleted.

Can be solved by useApolloClient as that will allow multiple queries being fired at once.

const client = useApolloClient();
client.query({
        query: GET_DOG_PHOTO,
        variables: { breed: 'bulldog' },
      });
Related