Dependent Query
Problem
Components attempt to fetch data before required information is available, causing errors or null reference exceptions. Fetching user preferences before knowing the user ID, or loading order details before getting the order number results in failed requests. Developers manually coordinate request timing with complex conditional logic and lifecycle dependencies.
Solution
Chain data fetching operations where subsequent requests depend on results from prior ones. This ensures you only fetch what’s needed while maintaining correct sequencing for dependent data.
Example
This example demonstrates chaining queries where fetching preferences depends on first getting the user ID.
// First query: Fetch user data
const { data: user } = useQuery('user', fetchUser);
// Second query: Only fetch preferences when user ID is available
const { data: preferences } = useQuery(
['preferences', user?.id], // Include user.id in cache key
() => fetchPreferences(user.id), // Fetch preferences using user ID
{ enabled: !!user?.id } // Only run when user.id exists
);
Benefits
- Prevents errors from fetching data before prerequisites are available.
- Ensures correct sequencing of dependent API requests.
- Avoids wasted requests by only fetching when dependencies are ready.
- Simplifies component logic by declaratively expressing dependencies.
- Works well with data fetching libraries that support enabled conditions.
Tradeoffs
- Introduces sequential delays where parallel requests would be faster.
- Can create complex dependency chains that are hard to reason about.
- May cause cascading loading states that feel slow to users.
- Requires careful error handling at each step of the chain.
- Can be difficult to optimize for performance without careful planning.