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 ππ».