React-Query: How to useQuery when button is clicked

I am new to this react-query library.

I know that when I want to fetch data, with this library I can do something like this:

const fetchData = async()=>{...}

// it starts fetching data from backend with this line of code
const {status, data, error} = useQuery(myKey, fetchData());

It works. But how to trigger the data fetching only when a button is clicked? , I know I probably could do something like <Button onPress={() => {useQuery(myKey, fetchData())}}/> , but how to manage the returned data and status...


According to the API Reference, you need to change the enabled option to false to disable a query from automatically running. Then you refetch manually.

// emulates axios/fetch since useQuery expectes a Promise
const emulateFetch = _ => {
  return new Promise(resolve => {
    resolve([{ data: "ok" }]);
  });
};

const handleClick = () => {
  // manually refetch
  refetch();
};

const { data, refetch } = useQuery("key", emulateFetch, {
  refetchOnWindowFocus: false,
  enabled: false // turned off by default, manual refetch is needed
});

return (
  <div>
    <button onClick={handleClick}>Click me</button>
    {JSON.stringify(data)}
  </div>
);

Working sandbox here.
 

Bonus: you can pass anything that returns a boolean to enabled. That way you could create Dependant/Serial queries.

// Get the user
const { data: user } = useQuery(['user', email], getUserByEmail)
 
// Then get the user's projects
const { isIdle, data: projects } = useQuery(
  ['projects', user.id],
  getProjectsByUser,
  {
    // `user` would be `null` at first (falsy),
    // so the query will not execute until the user exists
    enabled: user,
  }
)

Looks like the documentation changed and is missing the manual querying section right now. Looking at the useQuery API however, you'd probably need to set enabled to false, and then use refetch to manually query when the button is pressed. You also might want to use force: true to have it query regardless of data freshness.


You have to pass the manual: true parameter option so the query doesn't fetch on mount. Also, you should pass fetchData without the parentheses, so you pass the function reference and not the value. To call the query you use refetch().

const {status, data, error, refetch} = useQuery(myKey, fetchData, {
      manual: true,
    });

const onClick = () => { refetch() }

Refer to the manual querying section on the react-query docs for more info https://github.com/tannerlinsley/react-query#manual-querying


There is another way to do this that also works if you want to trigger multiple refetches.

const [fetch, setFetch] = useState(null);
const query = useQuery(["endpoint", fetch], fetchData);

const refetch = () => setFetch(Date.now());

// call the refetch when handling click.

If you want to refetch multiple entities you could have a top level useState that is called for instance fetchAll and:

...
const query = useQuery(["endpoint", fetch, fetchAll], fetchData);
...

and this code will also trigger if you press a button to fetch all.