Skip to content

Commit 3d83ab3

Browse files
committed
feat: implement exact targeting for refetching queries to prevent unintended cascading effects
1 parent 84d8e93 commit 3d83ab3

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

packages/query-db-collection/src/query.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,7 @@ export function queryCollectionOptions<
634634
return queryClient.refetchQueries(
635635
{
636636
queryKey: queryKey,
637+
exact: true,
637638
},
638639
{
639640
throwOnError: opts?.throwOnError,

packages/query-db-collection/tests/query.test.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,6 +1633,81 @@ describe(`QueryCollection`, () => {
16331633
)
16341634
})
16351635

1636+
it(`should use exact targeting when refetching to avoid unintended cascading of related queries`, async () => {
1637+
// Create multiple collections with related but distinct query keys
1638+
const queryKey = [`todos`]
1639+
const queryKey1 = [`todos`, `project-1`]
1640+
const queryKey2 = [`todos`, `project-2`]
1641+
1642+
const mockItems = [{ id: `1`, name: `Item 1` }]
1643+
const queryFn = vi.fn().mockResolvedValue(mockItems)
1644+
const queryFn1 = vi.fn().mockResolvedValue(mockItems)
1645+
const queryFn2 = vi.fn().mockResolvedValue(mockItems)
1646+
1647+
const config: QueryCollectionConfig<TestItem> = {
1648+
id: `all-todos`,
1649+
queryClient,
1650+
queryKey: queryKey,
1651+
queryFn: queryFn,
1652+
getKey,
1653+
startSync: true,
1654+
}
1655+
const config1: QueryCollectionConfig<TestItem> = {
1656+
id: `project-1-todos`,
1657+
queryClient,
1658+
queryKey: queryKey1,
1659+
queryFn: queryFn1,
1660+
getKey,
1661+
startSync: true,
1662+
}
1663+
const config2: QueryCollectionConfig<TestItem> = {
1664+
id: `project-2-todos`,
1665+
queryClient,
1666+
queryKey: queryKey2,
1667+
queryFn: queryFn2,
1668+
getKey,
1669+
startSync: true,
1670+
}
1671+
1672+
const options = queryCollectionOptions(config)
1673+
const options1 = queryCollectionOptions(config1)
1674+
const options2 = queryCollectionOptions(config2)
1675+
1676+
const collection = createCollection(options)
1677+
const collection1 = createCollection(options1)
1678+
const collection2 = createCollection(options2)
1679+
1680+
// Wait for initial queries to complete
1681+
await vi.waitFor(() => {
1682+
expect(queryFn).toHaveBeenCalledTimes(1)
1683+
expect(queryFn1).toHaveBeenCalledTimes(1)
1684+
expect(queryFn2).toHaveBeenCalledTimes(1)
1685+
expect(collection.status).toBe(`ready`)
1686+
})
1687+
1688+
// Reset call counts to test refetch behavior
1689+
queryFn.mockClear()
1690+
queryFn1.mockClear()
1691+
queryFn2.mockClear()
1692+
1693+
// Refetch the target collection with key ['todos', 'project-1']
1694+
await collection1.utils.refetch()
1695+
1696+
// Verify that only the target query was refetched
1697+
await vi.waitFor(() => {
1698+
expect(queryFn1).toHaveBeenCalledTimes(1)
1699+
expect(queryFn).not.toHaveBeenCalled()
1700+
expect(queryFn2).not.toHaveBeenCalled()
1701+
})
1702+
1703+
// Cleanup
1704+
await Promise.all([
1705+
collection.cleanup(),
1706+
collection1.cleanup(),
1707+
collection2.cleanup(),
1708+
])
1709+
})
1710+
16361711
describe(`Error Handling`, () => {
16371712
// Helper to create test collection with common configuration
16381713
const createErrorHandlingTestCollection = (

0 commit comments

Comments
 (0)