# Parallel queries when working with React Query

# The Simple Approach: Multiple useQuery calls

This is the most straightforward when you need independent data in the same component:

```javascript
function Dashboard() {
  const { data: repos, isLoading: reposLoading } = useQuery({
    queryKey: ['repos'],
    queryFn: fetchRepos
  })
  
  const { data: members, isLoading: membersLoading } = useQuery({
    queryKey: ['members'], 
    queryFn: fetchMembers
  })

  // Each loads independently - great UX!
  if (reposLoading) return <div>Loading repos...</div>
  if (membersLoading) return <div>Loading members...</div>
  
  return (
    <div>
      <ReposList repos={repos} />
      <MembersList members={members} />
    </div>
  )
}
```

# useQueries for Dynamic Parallel Fetching

This is where it becomes really useful when you need to get data for an unknown number of items:

```javascript
function useRepoIssues(repos) {
  return useQueries({
    queries: repos?.map(repo => ({
      queryKey: ['repos', repo.name, 'issues'],
      queryFn: () => fetchIssues(repo.name)
    })) ?? []
  })
}

function ReposDashboard() {
  const { data: repos } = useQuery({
    queryKey: ['repos'],
    queryFn: fetchRepos
  })
  
  const issuesQueries = useRepoIssues(repos)
  
  // Derive total issues across all repos
  const totalIssues = issuesQueries
    .map(query => query.data?.length ?? 0)
    .reduce((sum, count) => sum + count, 0)
    
  return (
    <div>
      <h2>Total Issues: {totalIssues}</h2>
      {repos?.map((repo, index) => (
        <RepoCard 
          key={repo.id}
          repo={repo}
          issues={issuesQueries[index]?.data}
          isLoading={issuesQueries[index]?.isLoading}
        />
      ))}
    </div>
  )
}
```

# Shareable Query Options Pattern

```javascript
// queries.js
export const repoOptions = {
  queryKey: ['repos'],
  queryFn: fetchRepos,
  staleTime: 5 * 60 * 1000 // 5 minutes
}

export const membersOptions = {
  queryKey: ['members'],
  queryFn: fetchMembers,
  staleTime: 10 * 60 * 1000 // 10 minutes
}

// hooks.js
export const useRepos = () => useQuery(repoOptions)
export const useMembers = () => useQuery(membersOptions)

export const useReposAndMembers = () => useQueries({
  queries: [repoOptions, membersOptions]
})
```

# Real-World Example: User Profile Page

```javascript
function UserProfile({ userId }) {
  const queries = useQueries({
    queries: [
      {
        queryKey: ['user', userId],
        queryFn: () => fetchUser(userId)
      },
      {
        queryKey: ['user', userId, 'posts'],
        queryFn: () => fetchUserPosts(userId)
      },
      {
        queryKey: ['user', userId, 'followers'],
        queryFn: () => fetchUserFollowers(userId)
      }
    ]
  })

  const [user, posts, followers] = queries
  
  const isLoading = queries.some(q => q.isLoading)
  const hasError = queries.some(q => q.isError)
  
  if (isLoading) return <ProfileSkeleton />
  if (hasError) return <ErrorMessage />
  
  return (
    <div>
      <UserInfo user={user.data} />
      <PostsList posts={posts.data} />
      <FollowersList followers={followers.data} />
    </div>
  )
}
```

The main point is that **parallel queries offer the best of both worlds**. They allow for separate caching and management while also providing coordinated loading states when needed. This is much better than using Promise.all, which ties everything together!
