Skip to content

RTK Query subscriptions do not update in React portals rendered into a new window #5085

@HMemmi

Description

@HMemmi

What I’m doing

I’m building a feature where the user can “pop out” a panel into a new browser window.
I create the new window and render React content into it via createPortal:

const [container, setContainer] = useState(null);
const [panelWindow, setPanelWindow] = useState(null);

useEffect(() => {
  const popup = window.open("", "_blank", "width=600,height=800");
  if (!popup) return;

  const el = popup.document.createElement("div");
  popup.document.body.appendChild(el);

  setPanelWindow(popup);
  setContainer(el);

  return () => popup.close();
}, []);

if (!container || !panelWindow) return null;

//wrapped by the same Redux <Provider>
return createPortal(
  <Panel />,
  container
);

The Panel contains RTK Query hooks (useGetXQuery, useMutation, etc.) that subscribe to data.

What works
• If I use vanilla Redux slices (dispatch / useSelector), the panel updates correctly in the new window.
• If I use axios + useState, it also works fine.
• RTK Query mutations (usePatchSomethingMutation) dispatch correctly and update the cache.
• Redux DevTools shows the cache entry as updated and fulfilled.

What breaks
• Components rendered into the new window with RTK Query hooks (useGetXQuery) do not re-render when the cache updates.
• debugValue inside the hook shows the updated data (e.g. 39 rows), but data / currentData in the component remain stale (e.g. 38 rows).
• If I force any re-render (resizing, dispatching a dummy action, or making the main window visible by even a single pixel), the panel updates immediately with the correct data.
• This only happens when the new window is maximized; if the main window is visible even slightly or the popup is resized, the panel updates immediately.

Why I think this is happening
• RTK Query hooks rely on useSyncExternalStore subscriptions.
• useSyncExternalStore seems tied to the main document visibility/focus for scheduling updates.
• Since the component tree is portaled into a different window.document, subscriptions don’t flush updates until the main document becomes visible again.
• Plain Redux works because reducers just update state immediately, without visibility checks.

Steps to reproduce

  1. Render an RTK Query-enabled component into a new window using createPortal.
  2. Maximize the new window.
  3. Trigger a mutation that updates the cached query data.
  4. Observe: DevTools shows the cache updated, but the new window UI does not.
  5. Force a re-render (resize window, dispatch dummy action, show main document). Now the new window updates.

Expected behavior
RTK Query subscriptions should notify and re-render components in any window as long as they are part of the same React tree + Redux store. Visibility of the original document should not matter.

Workarounds tried
• refetch() → does not help.
• Dispatching a dummy action → works, but hacky.
• Separate React root in popup with → still broken for RTK Query (but plain Redux works fine).

Environment
• React 19.1.0
• Redux Toolkit 2.9.0
• Browser: Chrome (latest), also reproduced in Firefox

Here is a minimal reproducible example: https://codesandbox.io/p/sandbox/zpqhcz

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions