14

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!

5 Answers5

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)
}
kurtko
  • 1,978
  • 4
  • 30
  • 47
  • 2
    in @apollo/react-hooks@4.0.0, refetch accept the parameter as variable (no need to put inside variables properties. So it's `refetch({ email: values.email })` – deathemperor Jun 08 '21 at 03:36
9

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]
  )
}
  • Thank you mate! This is great. – Pavel Schoffer Aug 13 '21 at 17:57
  • 1
    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. – Jeremy Feb 18 '22 at 15:38
6

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 }});
}
apacheco37
  • 81
  • 1
  • 5
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;
dpatra
  • 52
  • 8
0

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)