fix re render issue

This commit is contained in:
Dinh Long Nguyen 2025-09-18 23:11:50 +07:00
parent f237936b0c
commit a39c38e1fd
5 changed files with 19 additions and 24 deletions

View File

@ -1,4 +1,4 @@
import React from 'react'
import React, { memo } from 'react'
/**
* Checks if an avatar is a custom image (starts with '/images/')
@ -16,7 +16,7 @@ interface AvatarEmojiProps {
textClassName?: string
}
export const AvatarEmoji: React.FC<AvatarEmojiProps> = ({
export const AvatarEmoji: React.FC<AvatarEmojiProps> = memo(({
avatar,
imageClassName = 'w-5 h-5 object-contain',
textClassName = 'text-base',
@ -27,4 +27,4 @@ export const AvatarEmoji: React.FC<AvatarEmojiProps> = ({
}
return <span className={textClassName}>{avatar}</span>
}
})

View File

@ -28,12 +28,12 @@ const useThinkingStore = create<ThinkingBlockState>((set) => ({
const ThinkingBlock = ({ id, text }: Props) => {
const { thinkingState, setThinkingState } = useThinkingStore()
const { streamingContent } = useAppState()
const isStreaming = useAppState((state) => !!state.streamingContent)
const { t } = useTranslation()
// Check for thinking formats
const hasThinkTag = text.includes('<think>') && !text.includes('</think>')
const hasAnalysisChannel = text.includes('<|channel|>analysis<|message|>') && !text.includes('<|start|>assistant<|channel|>final<|message|>')
const loading = (hasThinkTag || hasAnalysisChannel) && streamingContent
const loading = (hasThinkTag || hasAnalysisChannel) && isStreaming
const isExpanded = thinkingState[id] ?? (loading ? true : false)
const handleClick = () => {
const newExpandedState = !isExpanded

View File

@ -87,7 +87,10 @@ export const ThreadContent = memo(
[]
)
const image = useMemo(() => item.content?.[0]?.image_url, [item])
const { streamingContent } = useAppState()
// Only check if streaming is happening for this thread, not the content itself
const isStreamingThisThread = useAppState(
(state) => state.streamingContent?.thread_id === item.thread_id
)
const text = useMemo(
() => item.content.find((e) => e.type === 'text')?.text?.value ?? '',
@ -360,10 +363,7 @@ export const ThreadContent = memo(
<div
className={cn(
'flex items-center gap-2',
item.isLastMessage &&
streamingContent &&
streamingContent.thread_id === item.thread_id &&
'hidden'
item.isLastMessage && isStreamingThisThread && 'hidden'
)}
>
<EditMessageDialog
@ -394,11 +394,7 @@ export const ThreadContent = memo(
</div>
<TokenSpeedIndicator
streaming={Boolean(
item.isLastMessage &&
streamingContent &&
streamingContent.thread_id === item.thread_id
)}
streaming={Boolean(item.isLastMessage && isStreamingThisThread)}
metadata={item.metadata}
/>
</div>

View File

@ -1,3 +1,4 @@
import { memo } from 'react'
import { useAppState } from '@/hooks/useAppState'
import { toNumber } from '@/utils/number'
import { Gauge } from 'lucide-react'
@ -7,11 +8,11 @@ interface TokenSpeedIndicatorProps {
streaming?: boolean
}
export const TokenSpeedIndicator = ({
export const TokenSpeedIndicator = memo(({
metadata,
streaming,
}: TokenSpeedIndicatorProps) => {
const { tokenSpeed } = useAppState()
const tokenSpeed = useAppState((state) => state.tokenSpeed)
const persistedTokenSpeed =
(metadata?.tokenSpeed as { tokenSpeed: number })?.tokenSpeed || 0
@ -38,6 +39,6 @@ export const TokenSpeedIndicator = ({
</span>
</div>
)
}
})
export default TokenSpeedIndicator

View File

@ -33,8 +33,6 @@ import {
} from '@/utils/reasoning'
export const useChat = () => {
const prompt = usePrompt((state) => state.prompt)
const setPrompt = usePrompt((state) => state.setPrompt)
const tools = useAppState((state) => state.tools)
const updateTokenSpeed = useAppState((state) => state.updateTokenSpeed)
const resetTokenSpeed = useAppState((state) => state.resetTokenSpeed)
@ -88,12 +86,14 @@ export const useChat = () => {
let currentThread = retrieveThread()
if (!currentThread) {
// Get prompt directly from store when needed
const currentPrompt = usePrompt.getState().prompt
currentThread = await createThread(
{
id: selectedModel?.id ?? defaultModel(selectedProvider),
provider: selectedProvider,
},
prompt,
currentPrompt,
selectedAssistant
)
router.navigate({
@ -104,7 +104,6 @@ export const useChat = () => {
return currentThread
}, [
createThread,
prompt,
retrieveThread,
router,
selectedModel?.id,
@ -241,7 +240,7 @@ export const useChat = () => {
if (troubleshooting)
addMessage(newUserThreadContent(activeThread.id, message, attachments))
updateThreadTimestamp(activeThread.id)
setPrompt('')
usePrompt.getState().setPrompt('')
try {
if (selectedModel?.id) {
updateLoadingModel(true)
@ -554,7 +553,6 @@ export const useChat = () => {
updateStreamingContent,
addMessage,
updateThreadTimestamp,
setPrompt,
selectedModel,
currentAssistant,
tools,