Wait for useLazyQuery response
Asked Answered
A

5

16

I need to call a query when submit button is pressed and then handle the response.

I need something like this:

const [checkEmail] = useLazyQuery(CHECK_EMAIL)
const handleSubmit = async () => {
  const res = await checkEmail({ variables: { email: values.email }})
  console.log(res) // handle response
}

Try #1:

const [checkEmail, { data }] = useLazyQuery(CHECK_EMAIL)
const handleSubmit = async () => {
  const res = await checkEmail({ variables: { email: values.email }})
  console.log(data) // undefined the first time
}

Thanks in advance!

Alcina answered 31/5, 2020 at 21:11 Comment(0)
A
10

After all, this is my solution.

export function useLazyQuery<TData = any, TVariables = OperationVariables>(query: DocumentNode) {
  const client = useApolloClient()
  return React.useCallback(
    (variables: TVariables) =>
      client.query<TData, TVariables>({
        query: query,
        variables: variables,
      }),
    [client]
  )
}
Alcina answered 3/6, 2020 at 1:9 Comment(2)
Thank you mate! This is great.Beadle
Is this just a closure of client / apollo client so response is held in the closure - won't it be immediately invoked? UseLazy is supposed to be at call- but i guess that doesn't matter for the client, so i guess this is really good! Big brain stuff! Confused and interested, would love some more detail.Bortman
G
19

This works for me:

const { refetch } = useQuery(CHECK_EMAIL, {
  skip: !values.email
})

const handleSubmit = async () => {
  const res = await refetch({ variables: { email: values.email }})
  console.log(res)
}
Gca answered 15/12, 2020 at 16:5 Comment(1)
in @apollo/[email protected], refetch accept the parameter as variable (no need to put inside variables properties. So it's refetch({ email: values.email })Mayoralty
A
10

After all, this is my solution.

export function useLazyQuery<TData = any, TVariables = OperationVariables>(query: DocumentNode) {
  const client = useApolloClient()
  return React.useCallback(
    (variables: TVariables) =>
      client.query<TData, TVariables>({
        query: query,
        variables: variables,
      }),
    [client]
  )
}
Alcina answered 3/6, 2020 at 1:9 Comment(2)
Thank you mate! This is great.Beadle
Is this just a closure of client / apollo client so response is held in the closure - won't it be immediately invoked? UseLazy is supposed to be at call- but i guess that doesn't matter for the client, so i guess this is really good! Big brain stuff! Confused and interested, would love some more detail.Bortman
P
7

You could also use the onCompleted option of the useLazyQuery hook like this:

const [checkEmail] = useLazyQuery(CHECK_EMAIL, {
  onCompleted: (data) => {
    console.log(data);
  }
});

const handleSubmit = () => {
  checkEmail({ variables: { email: values.email }});
}
Plucky answered 23/3, 2022 at 20:0 Comment(0)
W
1

Simply do the following:

import { useLazyQuery } from '@apollo/client';

const [myQuery] = useLazyQuery(MY_GQL_QUERY)

const result = await myQuery({ variables: { some: 'variable' }})
console.log(result.data)
Weslee answered 30/6, 2023 at 13:1 Comment(0)
Q
0

In case someone wants to fetch multiple apis at single load, it could be achieved like this.

  • On Demand Load > e.g. onClick, onChange
  • On Startup > e.g. useEffect
import { useLazyQuery } from "@apollo/client";
import { useState, useEffect } from "react";
import { GET_DOGS } from "../../utils/apiUtils";
    
const DisplayDogsLazy = () => {
  const [getDogs] = useLazyQuery(GET_DOGS);
  const [data, setData] = useState([]);
    
    useEffect(() => {
     getAllData();
    }, []);

    const getAllData = async () => {
        const response = await getDogs();
        console.log("Awaited response >", response);
    };
    
      const handleGetDogsClick = async () => {
        const response = await getDogs();
        setData(response.data.dogs);
      };
    
      return (
        <>
          <button onClick={handleGetDogsClick}>Get Dogs</button>
    
          {data?.length > 0 && (
            <ul>
              {data?.map((dog) => (
                <li key={dog.id} value={dog.breed}>
                  {dog.breed}
                </li>
              ))}
            </ul>
          )}
        </>
      );
    };
    
export default DisplayDogsLazy;
Quotha answered 31/12, 2022 at 3:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.