Conditionally calling queries in React Query

Photo by Rich Tervet on Unsplash

Conditionally calling queries in React Query

Note to the reader: This article uses the most current version of react-query, also known as @tanstack/react-query, which is currently at version 5. If you're interested in learning more about the updates in this newer version, you can find further details here.

In this article, we'll explore how to handle conditional and dependent queries efficiently with React Query.

When you call useQuery, it will trigger a fetch request automatically. However, this could be inconvenient if you prefer to delay the request. This delay might be necessary due to user interactions or because your query relies on specific information to complete successfully.

Here's what the typical implementation looks like:

useQuery({ 
  queryKey: 'my-key', 
  queryFn: () => request(),
});

Luckily, the useQuery hook comes with a handy optional property called enabled. This property, a boolean, allows you to control when the request is sent. Even though it might seem like the fetch request is initiated when you call the hook in your component, the enabled property can prevent this from occurring.

useQuery({ 
  queryKey: 'my-key', 
  queryFn: () => requeset(), 
  // The query won't run until the value of shouldFetch is set to true.
  enabled: shouldFetch 
});

Having the option to dynamically enable when the query will be triggered, allows us to handle two widespread use cases when developing web applications:

  • Queries dependent on a condition (i.e. user interaction)

  • Queries dependent on each other

Queries dependent on a condition

In this example, the condition that needs to be fulfilled is a user interaction. The useQuery hook is called, but it relies on the enabled property being set to the boolean value of the id. Since the id initially starts as null, the query won’t be triggered.

When the user interacts with the <input /> and chooses an ID, it initiates a state update, setting the ID to the new value. Consequently, the enabled value (in this case, the ID) becomes true.

const GetUser = () => {
  const [id, setId] = useState();

  const { data } = useQuery({
    queryKey: 'user', 
    queryFn: () => requeset(), 
    enabled: Boolean(id)
  });

  const onChange = (e) => {
    setId(e.target.value);
  }

  return (
    <>
      <label for="id">Pick a user ID:</label>
      <input type="number" id="id" name="id" min="0">
      {data && JSON.stringigy(data)}
    </>
  );
}

Queries dependent on each other

Frequently, API interactions are reliant on the outcomes of previous API interactions.

In the case of dependent queries, they need the successful completion of preceding queries before they can be executed.

Let's illustrate this concept:

const { data: posts } = useQuery({ 
  queryKey: 'posts', 
  queryFn: () => getPosts,
});
const latestPost = posts[post?.length - 1];

const { data: comments } useQuery({
  queryKey: 'comments', 
  queryFn: () => getComments({ postId: latestPost.id }),
  enabled: Boolean(latestPost?.id);
});

In this example, we're invoking two queries, but only the first one (getPosts) is immediately triggered. The second query (getComments) aims to fetch comments for the latest blog post. However, it relies on the id from that post, we can use the same id for the enable property to decide when the query should be initiated.

Conclusion

By leveraging the enabled property in the useQuery hook, we've learned how to control when a request is sent, enabling us to address common use cases in web application development.

Hope you enjoyed the read πŸ™‚, until the next post πŸ‘‹πŸ».

Β