RelationshipTable: join table with an async server Cell blanks the whole admin when cacheComponents is enabled

Open Beginner friendly
#19,268 2 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@isaac-openmic is already working on this.

Since Nov 2, 2026.

  • #19272 by @isaac-openmic — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
62/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Domain
frontend, web-dev

Research direction

The async state updates after getTableState resolves in packages/ui/src/elements/RelationshipTable/index.tsx, around lines 157 and 172-175. Read how the table and column state are set there, then reproduce with the linked repro under cacheComponents enabled, checking that the admin no longer goes blank while the table streams. Done means "Loading…" stays visible until the table arrives, with the same behaviour when cacheComponents is off.

Written by the indexing model from the issue text.

Description

area: ui Bug
Describe the Bug

With cacheComponents: true, opening a document whose join field shows a column with an async server Cell hides the entire admin, not just the table, until every cell has loaded.

RelationshipTable awaits getTableState and applies the result with plain state setters, outside a transition (index.tsx#L157, #L172-L175). getTableState resolves while the returned Table is still streaming, so rendering it suspends. With cacheComponents on, withPayload sets PAYLOAD_CACHE_COMPONENTS_ENABLED (withPayload.js#L40) and the root layout wraps the admin in <Suspense fallback={null}> (Root/index.tsx#L52-L53), so the suspension reaches that boundary and the page goes blank.

Expected: "Loading…" stays until the table has arrived, as it does with cacheComponents: false.

Applying the result in a transition fixes it (verified on the reproduction: "Loading…" stays until the whole table is in, and the page never blanks):

-import React, { Fragment, useCallback, useEffect, useRef, useState } from 'react'
+import React, { Fragment, startTransition, useCallback, useEffect, useRef, useState } from 'react'
@@
-      setData(newData)
-      setTable(NewTable)
-      setColumnState(newColumnState)
-      setIsLoadingTable(false)
+      startTransition(() => {
+        setData(newData)
+        setTable(NewTable)
+        setColumnState(newColumnState)
+        setIsLoadingTable(false)
+      })

The same code is unchanged on 3.x and main. 4.0.0-beta.6 doesn't show the symptom because its root layout no longer wraps the admin in Suspense, but the cause in RelationshipTable remains.

Link to the code that reproduces this issue

https://github.com/isaac-openmic/upstream-repros/tree/main/payload-19268

Reproduction Steps
  1. npm install && npm run build && npm start
  2. Log in at http://localhost:3000/admin as [email protected] / test (seeded on first start).
  3. Open Teams → Team. The Members table shows "Loading…", then the whole admin goes blank for ~1.5 s (the Cell's timer), then the full table appears.
Which area(s) are affected?

area: ui

Environment Info
payload: 3.92.1
@payloadcms/next, @payloadcms/ui, @payloadcms/db-sqlite: 3.92.1
next: 16.3.3 (production build, cacheComponents: true)
react / react-dom: 19.2.6
node: 24.22.2
Dominant language
TypeScript
Stars
45.6k
Forks
4.4k
Avg merge
1d 16h
Merged PRs (30d)
288

Getting set up

Open in Codespaces

Starts the project's dev container in your browser, under your own GitHub account.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from payloadcms/payload

All issues in payloadcms/payload

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.