react-streamdown: code blocks keep the previous highlighter when components change without new text
changing components.SyntaxHighlighter, components.CodeHeader or an entry of componentsByLanguage on StreamdownTextPrimitive does not update code blocks that are already rendered until their text changes. reproduced in streaming and static mode on f36e94500 and on 69c3d0f17 (before #7651):
const view = (SyntaxHighlighter: ComponentType<SyntaxHighlighterProps>) => (
<TextMessagePartProvider text={"```ts\nconst x = 1;\n```"} isRunning={false}>
<StreamdownTextPrimitive
mode="static"
componentsByLanguage={{ ts: { SyntaxHighlighter } }}
/>
</TextMessagePartProvider>
);
const { rerender } = render(view(First));
rerender(view(Second));
// First is still rendered and Second never rendersuseAdaptedComponents hands streamdown a code component that is a stable useCallbackRef wrapper (#7082), and StreamdownTextPrimitive stabilizes the components map, so streamdown receives the same props. streamdown 2.6.0's Streamdown memo does not compare components, and its Block memo compares entries by identity, so nothing re-renders; the new adapter only reaches a block the next time that block re-renders for another reason, such as new text or an animated message completing.
a fix has to let an adapter change reach settled blocks without bringing back a re-render per streamed token, for example by giving the code entry a new identity only when the adapter's components change.
Source: assistant-ui/assistant-ui