how can I fetch data from useQuery hook after a form submission in Apollo?

Viewed 3716

I have a search state in react function component.

  const [search, setSearch] = React.useState({
    orgName: "",
    repoName: ""
  });

so, when the user submits a form. I need to fetch data from the search object. What I did was:

const handleSearch = (e) => {
        e.preventDefault();
        const {loading, data, error} = useQuery(SEARCH_REPO, {
            variables : {orgName : search.orgName, repoName: search.repoName}
        });
  };

which violated the react hooks first rule. And I get the error was hooks cannot be used in non react functional component. So, what is the alternative how can I use it. Is it okay to put the useQuery in useEffect hook which will refetch the data when the search object updates?

2 Answers

If you need to execute a query in response to a user action, like a button press, you shouldn't use useQuery at all -- that's what useLazyQuery is for. The useLazyQuery hook will return a tuple (just like useMutation) that consists of a function to execute the query and an object with the query results. It's used just like you would use useMutation, except that it does not return a Promise.

const [search, {loading, data, error}] = useLazyQuery(SEARCH_REPO, {
  variables : {orgName : search.orgName, repoName: search.repoName}
});
const handleSearch = (e) => {
  e.preventDefault();
  search();
};

You've identified the problem correctly in that hooks need to be at top level. Putting useQuery in useEffect is going to lead to the same problem.

With your event handler, you could do something like put the useQuery at the top level and calling the refetch in the handler (fourth thing it returns from the useQuery). If you know your component is going to update on the event, just having the useQuery get the data at the top level (but not in the useEffect) is also effective.

Related