react-query: Refetch Query only if the state variable is changed
Asked Answered
S

3

28

I have a select option menu. So, When a user selects an option, I want send a GET/ request to the server with that option and recieve the filtered data from server.

This can be achived using useEffect(() => {// send the request}, [criteria])

Because, useEffect ensures that the request will send to server only if the setCriteria is finished.

But, I am using react-query library. so that, it is not allowed to use useQuery inside useEffect.

As A result, the request is send to server before it the setState is completed. So that, server gets the previous selected value, not the currently selected value.

onChange:

<select
  name="filter"
  value={criteria}
  onChange={async (e) => {
    setCriteria(e.target.value);
  }}
>
  <option>Most recent First</option>
  <option>Price: Low to High</option>
  <option>Price: High to Low</option>
</select>;

Fetch posts:

 const FetchPosts = async () => {
    const {
      data: { posts },
    } = await axios.get(`${process.env.API_URL}/api/posts`, {
      params: {
        filter: criteria,
      },
    });

    return posts;
  };

 useQuery("posts", FetchPosts);

 const posts = queryCache.getQueryData("posts");
Safford answered 14/11, 2020 at 4:26 Comment(0)
A
67

You can use your criteria as query key. Whenever a query's key changes, the query will automatically update.

const FetchPosts = async ({criteria}) => {
    console.log(criteria) //from useQuery key

    //your get api call here with criteria params

    return posts;
};

const [criteria, setCriteria] = useState("")

const {isLoading, data: post} = useQuery(["posts", criteria], FetchPosts); //include criteria state to query key

console.log(post) 

<select
  name="filter"
  value={criteria}
  onChange={(e) => {
    setCriteria(e.target.value);  // trigger a re-render and cause the useQuery to run the query with the newly selected criteria
  }}
>
  <option>Most recent First</option>
  <option>Price: Low to High</option>
  <option>Price: High to Low</option>
</select>
Alainaalaine answered 14/11, 2020 at 6:59 Comment(4)
I have a different use case. How do I NOT fire the useQuery on every criterion change? I only want to fetch during the initial render and when an action is triggered (ex: Apply Filter button click)Putrescine
@Putrescine I have the same doubt, any solutions?Bennet
@Putrescine and @Bennet If you don't set your parameter as part of the query key, your query will not fire on criterion changes. For example: useQuery("thisIsAStaticKey", doSomething());Pung
Thanks man! Can I also do this for multiple arrays?Firstborn
S
31

Question is already answered. Here's my two cents:

Treat useQuery's query keys like a dependency array of useEffect. Whenever the key changes query gets executed.

If you still want to control the firing of queries, you may explore the "enabled" option to the useQuery hook.

Stereopticon answered 19/5, 2021 at 16:17 Comment(1)
Hi, can we send json body in get request of useQuery ?Arbuthnot
B
3

Passing criteria value to useQuery key will trigger function execution when the value changes, also don't forget to pass the criteria to the fetcher for the param to work with the key

const FetchPosts = async (criteria) => {
  const {
    data: { posts },
  } = await axios.get(`${process.env.API_URL}/api/posts`, {
    params: {
      filter: criteria,
    },
  });

  return posts;
};

const [criteria, setCriteria] = useState('');
useQuery(['posts', criteria], () => FetchPosts(criteria));
Bathilda answered 20/7, 2023 at 4:10 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Extent

© 2022 - 2025 — McMap. All rights reserved.