Skip to content

fix(studio): give the chat transcript and composer distinct React keys - #74

Open
mhmdjaouhari wants to merge 1 commit into
flowtricks:mainfrom
mhmdjaouhari:fix/chat-panel-distinct-keys
Open

mhmdjaouhari wants to merge 1 commit into
flowtricks:mainfrom
mhmdjaouhari:fix/chat-panel-distinct-keys

Conversation

@mhmdjaouhari

Copy link
Copy Markdown

Found this bug while experimenting with the Studio. The chat history gets duplicated infinitely after a while making the UI unusable. See image at the bottom of the description.

A test has been added but maybe it's not necessary.

More details below generated by Opus 5.5:

fix(studio): give the chat transcript and composer distinct React keys

Problem

ChatPanel rendered <ChatMessages key={chat.id}> and <ChatComposer key={chat.id}> as siblings. Duplicate sibling keys make React's reconciler drop one old fiber from its key map without removing its DOM node. In a chat with history, every render (every keystroke, every streamed update) left an orphaned transcript in the page. The result was stacked, separately scrolling copies of the conversation, "Thinking through your request…" rows that never cleared, and a composer pushed off-screen.

Scope

  • React 18.3.1 behaves the same in its development and production builds. Only the "two children with the same key" warning differs, and production builds don't print it, which is why the bug went unnoticed.
  • This affects every place Studio runs: the hosted Worker/container, astro-studio dev, and the local Studio that Desktop opens in the browser. All of them serve the same ChatPanel. The Desktop (Electron) renderer has no AI chat panel.

Fix

The keys are now messages-${chat.id} and composer-${chat.id}. They still reset each part's local state when the user switches chats, and they no longer collide.

Tests

  • test/ai.browser.ts: new verifySingleTranscript seeds a saved chat with two messages in IndexedDB, reloads, types six characters, and asserts exactly one .chat-transcript.
    • With the fix: passes.
    • Without the fix: 10 transcripts.
  • Known issue, not caused by this change: verifyImages already times out waiting for the "Choose PNG" alert on main, so the full ai.browser.ts run stops before reaching the new check. The new check was run on its own against the fixture site.
  • npm run check, ESLint and Prettier pass for Studio.

pic-selected-261105-2106-15

ChatPanel keyed both ChatMessages and ChatComposer with chat.id under the
same parent. With duplicate sibling keys, React's reconciler drops one of
the old fibers from its key map without deleting its DOM node, so every
render of a chat with history left an orphaned transcript in the page.
The stale copies scrolled independently, kept "Thinking through your
request…" rows that never cleared, and pushed the composer off-screen.

The behaviour is the same in React's development and production builds;
only the "two children with the same key" warning differs. It affects
every place Studio runs: the hosted Worker/container, `astro-studio dev`,
and the local Studio that Desktop opens in the browser. The Desktop
renderer has no chat panel of its own.

Prefixing the keys keeps the intended reset-on-chat-switch behaviour and
makes the siblings distinct. The browser suite now seeds a saved chat,
types six characters, and asserts a single transcript; without the fix
it finds ten.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant