Ashik
Ashik

Reputation: 3448

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

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");

Upvotes: 29

Views: 69105

Answers (3)

av.dev
av.dev

Reputation: 341

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.

Upvotes: 34

William Suarez
William Suarez

Reputation: 41

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));

Upvotes: 4

Chanandrei
Chanandrei

Reputation: 2421

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>

Upvotes: 69

Related Questions