perf: prevent unnecessary topic rerendering (#8116)

This commit is contained in:
one 2025-07-14 13:43:01 +08:00 committed by GitHub
parent 19a8d9e9b3
commit c6554c8f80
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 29 additions and 16 deletions

View File

@ -18,8 +18,8 @@ import { getStoreSetting } from './useSettings'
let _activeTopic: Topic
let _setActiveTopic: (topic: Topic) => void
export function useActiveTopic(_assistant: Assistant, topic?: Topic) {
const { assistant } = useAssistant(_assistant.id)
export function useActiveTopic(assistantId: string, topic?: Topic) {
const { assistant } = useAssistant(assistantId)
const [activeTopic, setActiveTopic] = useState(topic || _activeTopic || assistant?.topics[0])
_activeTopic = activeTopic

View File

@ -3,8 +3,8 @@ import { useSettings } from '@renderer/hooks/useSettings'
import { useActiveTopic } from '@renderer/hooks/useTopic'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
import NavigationService from '@renderer/services/NavigationService'
import { Assistant } from '@renderer/types'
import { FC, useEffect, useState } from 'react'
import { Assistant, Topic } from '@renderer/types'
import { FC, startTransition, useCallback, useEffect, useState } from 'react'
import { useLocation, useNavigate } from 'react-router-dom'
import styled from 'styled-components'
@ -21,12 +21,31 @@ const HomePage: FC = () => {
const location = useLocation()
const state = location.state
const [activeAssistant, setActiveAssistant] = useState(state?.assistant || _activeAssistant || assistants[0])
const { activeTopic, setActiveTopic } = useActiveTopic(activeAssistant, state?.topic)
const [activeAssistant, _setActiveAssistant] = useState(state?.assistant || _activeAssistant || assistants[0])
const { activeTopic, setActiveTopic: _setActiveTopic } = useActiveTopic(activeAssistant?.id, state?.topic)
const { showAssistants, showTopics, topicPosition } = useSettings()
_activeAssistant = activeAssistant
const setActiveAssistant = useCallback(
(newAssistant: Assistant) => {
startTransition(() => {
_setActiveAssistant(newAssistant)
// 同步更新 active topic避免不必要的重新渲染
const newTopic = newAssistant.topics[0]
_setActiveTopic((prev) => (newTopic?.id === prev.id ? prev : newTopic))
})
},
[_setActiveTopic]
)
const setActiveTopic = useCallback(
(newTopic: Topic) => {
startTransition(() => _setActiveTopic((prev) => (newTopic?.id === prev.id ? prev : newTopic)))
},
[_setActiveTopic]
)
useEffect(() => {
NavigationService.setNavigate(navigate)
}, [navigate])

View File

@ -39,7 +39,7 @@ import { Dropdown, MenuProps, Tooltip } from 'antd'
import { ItemType, MenuItemType } from 'antd/es/menu/interface'
import dayjs from 'dayjs'
import { findIndex } from 'lodash'
import { FC, startTransition, useCallback, useDeferredValue, useMemo, useRef, useState } from 'react'
import { FC, useCallback, useDeferredValue, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux'
import styled from 'styled-components'
@ -168,9 +168,7 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic
const onSwitchTopic = useCallback(
async (topic: Topic) => {
// await modelGenerating()
startTransition(() => {
setActiveTopic(topic)
})
setActiveTopic(topic)
},
[setActiveTopic]
)

View File

@ -25,7 +25,7 @@ import { hasTopicPendingRequests } from '@renderer/utils/queue'
import { Dropdown, MenuProps } from 'antd'
import { omit } from 'lodash'
import { AlignJustify, Plus, Settings2, Tag, Tags } from 'lucide-react'
import { FC, memo, startTransition, useCallback, useEffect, useMemo, useState } from 'react'
import { FC, memo, useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
import * as tinyPinyin from 'tiny-pinyin'
@ -125,12 +125,8 @@ const AssistantItem: FC<AssistantItemProps> = ({
if (topicPosition === 'left') {
EventEmitter.emit(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR)
}
onSwitch(assistant)
} else {
startTransition(() => {
onSwitch(assistant)
})
}
onSwitch(assistant)
}, [clickAssistantToShowTopic, onSwitch, assistant, topicPosition])
const assistantName = useMemo(() => assistant.name || t('chat.default.name'), [assistant.name, t])