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

View File

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

View File

@ -87,7 +87,10 @@ export const ThreadContent = memo(
[] []
) )
const image = useMemo(() => item.content?.[0]?.image_url, [item]) 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( const text = useMemo(
() => item.content.find((e) => e.type === 'text')?.text?.value ?? '', () => item.content.find((e) => e.type === 'text')?.text?.value ?? '',
@ -360,10 +363,7 @@ export const ThreadContent = memo(
<div <div
className={cn( className={cn(
'flex items-center gap-2', 'flex items-center gap-2',
item.isLastMessage && item.isLastMessage && isStreamingThisThread && 'hidden'
streamingContent &&
streamingContent.thread_id === item.thread_id &&
'hidden'
)} )}
> >
<EditMessageDialog <EditMessageDialog
@ -394,11 +394,7 @@ export const ThreadContent = memo(
</div> </div>
<TokenSpeedIndicator <TokenSpeedIndicator
streaming={Boolean( streaming={Boolean(item.isLastMessage && isStreamingThisThread)}
item.isLastMessage &&
streamingContent &&
streamingContent.thread_id === item.thread_id
)}
metadata={item.metadata} metadata={item.metadata}
/> />
</div> </div>

View File

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

View File

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