-
-
Notifications
You must be signed in to change notification settings - Fork 874
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is it possible to prevent remounting of components (<ReactMarkdown components={...}>) when markdown changes? #849
Comments
If we could just let the user specify a I checked many LLM chatbot frontends, they all have this problem. If this could get fixed then it will improve the quality of life for many developers! |
hmmm I tried again, is it as simple as this? <ReactMarkdown
components={{
code: SyntaxHighlighter
}}
>
{markdown}
</ReactMarkdown> If so then it is already possible?.. Let me confirm.. |
Sure. But it has nothing to do with this project. Just with react. You pass new components (new functions) each time. Don‘t. |
This comment has been minimized.
This comment has been minimized.
Thanks a lot @wooorm , it works.. import React, {useEffect, useState} from 'react';
import ReactMarkdown from 'react-markdown';
import {Prism as SyntaxHighlighter} from 'react-syntax-highlighter';
import {darcula} from 'react-syntax-highlighter/dist/esm/styles/prism';
const Code = ({className, children, ...props}) => {
const match = /language-(\w+)/.exec(className || '');
return match ? (
<SyntaxHighlighter
language={match[1]}
{...props}
style={darcula}
>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
) : (
<code className={className} {...props}>
{children}
</code>
);
};
const StreamingCodeBlock = () => {
const [markdown, setMarkdown] = useState('```javascript\n// Initial code\n');
useEffect(() => {
const interval = setInterval(() => {
setMarkdown(prev => prev + `console.log('New line ${Date.now()}');\n`);
}, 500);
return () => clearInterval(interval);
}, []);
return (
<ReactMarkdown components={{code: Code}}>
{markdown}
</ReactMarkdown>
);
}; But again I see a lot of Chatbot UIs doing it wrong, Maybe we could put a small hint in the documentation 😁. Using
is more efficient and more correct in many cases than a callback function (which was in the docs). |
I dunno, I feel like developers need to know some react themselves, how to memo-ize things, speed components up, be efficient. |
Initial checklist
Problem
When using ReactMarkdown with custom components (particularly for code blocks), any change to the markdown content causes the component to remount. This leads to issues such as loss of user selections and interactions within these components.
For example
If you try to select some code, each time the markdown is updated, the
<SyntaxHighlighter>
gets remounted, and user selection is lost.CleanShot.2024-07-31.at.19.07.39.mp4
The use case is with LLM chatbots.
Markdown content is often generated and displayed in a streaming fashion with LLM chatbots.
The user sees the beginning of the code and starts interacting with it (e.g., selecting parts of the code, placing the cursor for copying).
But with the current implementation, as the AI continues to generate more code, appending to the existing block, the ReactMarkdown component is remounted and the user selection is lost, leading to a frustrating experience for users who are trying to interact with the code while it's still being generated.
Solution
I don't have a solution - I'm not familiar with the internals of ReactMarkdown.
But I think this should be possible.
Alternatives
I tried but couldn't find any workaround. Updating code in ReactMarkdown to make it possible is the only solution.
The text was updated successfully, but these errors were encountered: