fix slow typing with long sessions (#4291)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import React, { useState, useEffect, useRef, memo, useMemo } from 'react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import remarkBreaks from 'remark-breaks';
|
||||
@@ -16,7 +16,14 @@ interface MarkdownContentProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const CodeBlock = ({ language, children }: { language: string; children: string }) => {
|
||||
// Memoized CodeBlock component to prevent re-rendering when props haven't changed
|
||||
const CodeBlock = memo(function CodeBlock({
|
||||
language,
|
||||
children,
|
||||
}: {
|
||||
language: string;
|
||||
children: string;
|
||||
}) {
|
||||
const [copied, setCopied] = useState(false);
|
||||
const timeoutRef = useRef<number | null>(null);
|
||||
|
||||
@@ -43,6 +50,44 @@ const CodeBlock = ({ language, children }: { language: string; children: string
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Memoize the SyntaxHighlighter component to prevent re-rendering
|
||||
// Only re-render if language or children change
|
||||
const memoizedSyntaxHighlighter = useMemo(() => {
|
||||
// For very large code blocks, consider truncating or lazy loading
|
||||
const isLargeCodeBlock = children.length > 10000; // 10KB threshold
|
||||
|
||||
if (isLargeCodeBlock) {
|
||||
console.log(`Large code block detected (${children.length} chars), consider optimization`);
|
||||
}
|
||||
|
||||
return (
|
||||
<SyntaxHighlighter
|
||||
style={oneDark}
|
||||
language={language}
|
||||
PreTag="div"
|
||||
customStyle={{
|
||||
margin: 0,
|
||||
width: '100%',
|
||||
maxWidth: '100%',
|
||||
}}
|
||||
codeTagProps={{
|
||||
style: {
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-all',
|
||||
overflowWrap: 'break-word',
|
||||
fontFamily: 'var(--font-sans)',
|
||||
},
|
||||
}}
|
||||
// Performance optimizations for SyntaxHighlighter
|
||||
showLineNumbers={false} // Disable line numbers for better performance
|
||||
wrapLines={false} // Disable line wrapping for better performance
|
||||
lineProps={undefined} // Don't add extra props to each line
|
||||
>
|
||||
{children}
|
||||
</SyntaxHighlighter>
|
||||
);
|
||||
}, [language, children]);
|
||||
|
||||
return (
|
||||
<div className="relative group w-full">
|
||||
<button
|
||||
@@ -54,47 +99,31 @@ const CodeBlock = ({ language, children }: { language: string; children: string
|
||||
>
|
||||
{copied ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
|
||||
</button>
|
||||
<div className="w-full overflow-x-auto">
|
||||
<SyntaxHighlighter
|
||||
style={oneDark}
|
||||
language={language}
|
||||
PreTag="div"
|
||||
customStyle={{
|
||||
margin: 0,
|
||||
width: '100%',
|
||||
maxWidth: '100%',
|
||||
}}
|
||||
codeTagProps={{
|
||||
style: {
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-all',
|
||||
overflowWrap: 'break-word',
|
||||
fontFamily: 'var(--font-sans)',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</SyntaxHighlighter>
|
||||
</div>
|
||||
<div className="w-full overflow-x-auto">{memoizedSyntaxHighlighter}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const MarkdownCode = React.forwardRef(function MarkdownCode(
|
||||
{ inline, className, children, ...props }: CodeProps,
|
||||
ref: React.Ref<HTMLElement>
|
||||
) {
|
||||
const match = /language-(\w+)/.exec(className || '');
|
||||
return !inline && match ? (
|
||||
<CodeBlock language={match[1]}>{String(children).replace(/\n$/, '')}</CodeBlock>
|
||||
) : (
|
||||
<code ref={ref} {...props} className="break-all bg-inline-code whitespace-pre-wrap font-sans">
|
||||
{children}
|
||||
</code>
|
||||
);
|
||||
});
|
||||
|
||||
export default function MarkdownContent({ content, className = '' }: MarkdownContentProps) {
|
||||
const MarkdownCode = memo(
|
||||
React.forwardRef(function MarkdownCode(
|
||||
{ inline, className, children, ...props }: CodeProps,
|
||||
ref: React.Ref<HTMLElement>
|
||||
) {
|
||||
const match = /language-(\w+)/.exec(className || '');
|
||||
return !inline && match ? (
|
||||
<CodeBlock language={match[1]}>{String(children).replace(/\n$/, '')}</CodeBlock>
|
||||
) : (
|
||||
<code ref={ref} {...props} className="break-all bg-inline-code whitespace-pre-wrap font-sans">
|
||||
{children}
|
||||
</code>
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
const MarkdownContent = memo(function MarkdownContent({
|
||||
content,
|
||||
className = '',
|
||||
}: MarkdownContentProps) {
|
||||
const [processedContent, setProcessedContent] = useState(content);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -137,4 +166,6 @@ export default function MarkdownContent({ content, className = '' }: MarkdownCon
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default MarkdownContent;
|
||||
|
||||
Reference in New Issue
Block a user