[query-broadcast-client-experimental] broadcastQueryClient: an `added` event overwrites a receiving query that has no data (e.g. in error) with the sender's empty state
维护者通常 1 天内回复
评估
- 难度
- 2/5
- 预计耗时
- 1-3 小时
- 新手友好度
- 25/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 停滞
- 技术栈
- react, typescript
调研方向
Read src/index.ts around lines 155–162 and 193–198 in the broadcast client package, then inspect the related change in #11391. The open pull request #12215 is already linked to this issue. Done means an added event no longer replaces a receiver’s settled error state with an empty pending state; the issue includes a minimal reproduction to check that behavior.
由索引模型根据 Issue 内容生成。
描述
Package: @tanstack/query-broadcast-client-experimental 5.104.3 (with @tanstack/query-core 5.104.3)
Describe the bug
When another tab creates a query, the receiving tab applies the sender's state on added whenever its own query has no data. A query that has no data but did settle (a failed query: status: 'error', errorUpdatedAt > 0) is replaced with the sender's brand-new state: status: 'pending', fetchStatus: 'idle', error: null, dataUpdatedAt: 0, errorUpdatedAt: 0.
The receiving query now looks like it is loading, but no fetch runs. Observers render a pending/loading UI indefinitely (until a refetch interval, focus or invalidation happens to trigger), and the error is lost.
src/index.ts, lines 193-198:
} else if (type === 'added') {
if (query) {
if (query.state.data === undefined) {
query.setState(state)
}
return
}
The sender posts added straight from queryCache.build, before its fetch starts (lines 155-162), so the state it carries is the initial empty state:
if (queryEvent.type === 'added') {
safePost({
type: 'added',
queryHash,
queryKey,
state,
})
}
Minimal reproduction
- Tab A and tab B both call
broadcastQueryClient({ queryClient }). - In tab A,
useQuery({ queryKey: ['x'], queryFn: () => Promise.reject(new Error('down')), retry: false }). It settles instatus: 'error', with no data. - Tab B creates the same query: either mount the same
useQuery, orqueryClient.getQueryCache().build(queryClient, { queryKey: ['x'] })(for example, as a side effect of a prefetch that has not started yet). - In tab A, the query is now
status: 'pending',fetchStatus: 'idle',error: null,errorUpdatedAt: 0. The observer shows loading, and no request is in flight.
Without the plugin, the same can be shown in a single client:
const query = queryClient.getQueryCache().find({ queryKey: ['x'] })! // in error, no data
query.setState({ status: 'pending', fetchStatus: 'idle', data: undefined, dataUpdatedAt: 0, error: null, errorUpdatedAt: 0 })
// observers now report pending with no fetch running
Expected behavior
An added event carries nothing the receiver lacks when the sender's query has never settled. The receiver should keep its own state, in particular an error.
Suggested fix
Skip an incoming added state that never received data or an error:
} else if (type === 'added') {
if (query) {
const incoming = state as QueryState
if (
query.state.data === undefined &&
(incoming.dataUpdatedAt > 0 || incoming.errorUpdatedAt > 0)
) {
query.setState(incoming)
}
return
}
A stricter variant would apply added only when it is newer than the receiver's last outcome (max(dataUpdatedAt, errorUpdatedAt)).
Workaround we use
Our query projection detects an observed query left pending with fetchStatus: 'idle' and refetches it once through its observer.
Related
Follow-up to #11391, which made added skip a receiver that already has data. A receiver without data but with an error is still overwritten.
- 主要语言
- TypeScript
- 星标
- 50.4k
- 派生
- 4.3k
- 平均合并
- 9 小时 42 分钟
- 30 天内合并 PR
- 590
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
TanStack/query 的其他 Issue
-
QueryClient.isFetching and useIsFetching accept a fetchStatus filter and ignore it可能已有人在做 @Apu-Emdad 于 8 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复
-
solid-query: STRICT_READ_UNTRACKED on Solid 2 — client()/options() read in component body (useMutation, useBaseQuery)可能重新可做 @LeonxLJX 于 48 天前认领,目前没有进行中的 PR。 未关闭
难度 2/5 1-3 小时 新手友好度 84/100
TanStack/query#11358 · 2 条评论 · 1 个 reaction ·
维护者通常 1 天内回复
-
useBaseQuery fetches the old query key when an <Activity> tree is revealed可能已有人在做 @lazerg 于 1 天前认领。 未关闭
难度 3/5 1-2 天 新手友好度 35/100
维护者通常 1 天内回复
-
solid-query 6.0.0-rc.5: onCacheEvent throws NotReadyError during a Solid 2 (rc.14+) transition landing可能已有人在做 @UzumakiODZ 于 7 天前认领。 未关闭
难度 4/5 3-5 天 新手友好度 28/100
TanStack/query#12031 · 2 条评论 ·
维护者通常 1 天内回复
-
Explicit gcTime schedules a GC timer during SSR, retaining the whole render in memory可能已有人在做 @AdzerKI 于 8 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 25/100
TanStack/query#12025 · 2 条评论 ·
维护者通常 1 天内回复
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 76/100
维护者通常 1 天内回复
-
bug
难度 1/5 1 小时以内 新手友好度 76/100
维护者通常 1 天内回复
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
难度 1/5 1 小时以内 新手友好度 76/100
lingdojo/kana-dojo#32964 · 1 条评论 · 5 个 reaction ·
维护者通常 1 天内回复
-
Documentation status: needs triage
难度 2/5 1-3 小时 新手友好度 72/100
mastra-ai/mastra#28194 · 1 条评论 ·
维护者通常 1 天内回复
-
priority-low refactor-3
难度 2/5 1-3 小时 新手友好度 84/100
维护者通常 3 天内回复