Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

[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

Đang mở
#12,213 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

@lazerg đang làm issue này rồi.

Từ ngày 20/10/2026.

  • #12215 của @lazerg — đang mở
  • #12282 của @vkpdeveloper — đang mở

Đánh giá

Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức phù hợp với người mới
25/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Đình trệ
Công nghệ
react, typescript

Hướng nghiên cứu

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.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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.

Ngôn ngữ chính
TypeScript
Star
50.4k
Fork
4.3k
Merge trung bình
9 giờ 42 phút
Pull request đã merge (30 ngày)
590

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của TanStack/query

Tất cả issue của TanStack/query

Issue tương tự

Thêm issue về TypeScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.