Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

[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

未关闭
#12,213 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

@lazerg 已经在做这个了。

开始于 2026年10月20日。

  • #12215 来自 @lazerg —— 未关闭
  • #12282 来自 @vkpdeveloper —— 未关闭

评估

难度
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

  1. Tab A and tab B both call broadcastQueryClient({ queryClient }).
  2. In tab A, useQuery({ queryKey: ['x'], queryFn: () => Promise.reject(new Error('down')), retry: false }). It settles in status: 'error', with no data.
  3. Tab B creates the same query: either mount the same useQuery, or queryClient.getQueryCache().build(queryClient, { queryKey: ['x'] }) (for example, as a side effect of a prefetch that has not started yet).
  4. 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

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

TanStack/query 的其他 Issue

查看 TanStack/query 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。