mirror of
https://github.com/langgenius/dify.git
synced 2026-05-10 05:56:31 +08:00
refactor(web): optimize model provider re-render and remove useEffect state sync
- Replace useEffect state sync with derived state pattern in useSystemDefaultModelAndModelList - Use useCallback instead of useMemo for function memoization in useProviderCredentialsAndLoadBalancing - Add memo() to ProviderAddedCard and CredentialPanel to prevent unnecessary re-renders - Switch to useProviderContextSelector for precise context subscription in ProviderAddedCard - Stabilize activate callback ref in useActivateCredential via supportedModelTypes ref - Add usage priority tooltip with i18n support
This commit is contained in:
parent
7471c32612
commit
1752edc047
@ -57,15 +57,21 @@ export const useSystemDefaultModelAndModelList: UseDefaultModelAndModelList = (
|
||||
|
||||
return currentDefaultModel
|
||||
}, [defaultModel, modelList])
|
||||
const currentDefaultModelKey = currentDefaultModel
|
||||
? `${currentDefaultModel.provider}:${currentDefaultModel.model}`
|
||||
: ''
|
||||
const [defaultModelState, setDefaultModelState] = useState<DefaultModel | undefined>(currentDefaultModel)
|
||||
const handleDefaultModelChange = useCallback((model: DefaultModel) => {
|
||||
setDefaultModelState(model)
|
||||
}, [])
|
||||
useEffect(() => {
|
||||
setDefaultModelState(currentDefaultModel)
|
||||
}, [currentDefaultModel])
|
||||
const [defaultModelSourceKey, setDefaultModelSourceKey] = useState(currentDefaultModelKey)
|
||||
const selectedDefaultModel = defaultModelSourceKey === currentDefaultModelKey
|
||||
? defaultModelState
|
||||
: currentDefaultModel
|
||||
|
||||
return [defaultModelState, handleDefaultModelChange]
|
||||
const handleDefaultModelChange = useCallback((model: DefaultModel) => {
|
||||
setDefaultModelSourceKey(currentDefaultModelKey)
|
||||
setDefaultModelState(model)
|
||||
}, [currentDefaultModelKey])
|
||||
|
||||
return [selectedDefaultModel, handleDefaultModelChange]
|
||||
}
|
||||
|
||||
export const useLanguage = () => {
|
||||
@ -116,7 +122,7 @@ export const useProviderCredentialsAndLoadBalancing = (
|
||||
predefinedFormSchemasValue?.credentials,
|
||||
])
|
||||
|
||||
const mutate = useMemo(() => () => {
|
||||
const mutate = useCallback(() => {
|
||||
if (predefinedEnabled)
|
||||
queryClient.invalidateQueries({ queryKey: ['model-providers', 'credentials', provider, credentialId] })
|
||||
if (customEnabled)
|
||||
|
||||
@ -4,6 +4,7 @@ import type {
|
||||
} from '../declarations'
|
||||
import type { CardVariant } from './use-credential-panel-state'
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { memo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Warning from '@/app/components/base/icons/src/vender/line/alertsAndFeedback/Warning'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
@ -41,10 +42,11 @@ const CredentialPanel = ({
|
||||
const updateModelList = useUpdateModelList()
|
||||
const updateModelProviders = useUpdateModelProviders()
|
||||
const state = useCredentialPanelState(provider)
|
||||
const providerName = provider.provider
|
||||
const modelProviderModelListQueryKey = consoleQuery.modelProviders.models.queryKey({
|
||||
input: {
|
||||
params: {
|
||||
provider: provider.provider,
|
||||
provider: providerName,
|
||||
},
|
||||
},
|
||||
})
|
||||
@ -72,7 +74,7 @@ const CredentialPanel = ({
|
||||
|
||||
const handleChangePriority = (key: PreferredProviderTypeEnum) => {
|
||||
changePriority({
|
||||
params: { provider: provider.provider },
|
||||
params: { provider: providerName },
|
||||
body: { preferred_provider_type: key },
|
||||
})
|
||||
}
|
||||
@ -156,4 +158,4 @@ function StatusLabel({ variant, credentialName }: {
|
||||
)
|
||||
}
|
||||
|
||||
export default CredentialPanel
|
||||
export default memo(CredentialPanel)
|
||||
|
||||
@ -6,7 +6,7 @@ import type { ModelProviderQuotaGetPaid } from '../utils'
|
||||
import type { PluginDetail } from '@/app/components/plugins/types'
|
||||
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useCallback } from 'react'
|
||||
import { memo, useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
AddCustomModel,
|
||||
@ -14,7 +14,7 @@ import {
|
||||
} from '@/app/components/header/account-setting/model-provider-page/model-auth'
|
||||
import { IS_CE_EDITION } from '@/config'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { useProviderContextSelector } from '@/context/provider-context'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { useModelProviderListExpanded, useSetModelProviderListExpanded } from '../atoms'
|
||||
@ -40,7 +40,7 @@ const ProviderAddedCard: FC<ProviderAddedCardProps> = ({
|
||||
pluginDetail,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { refreshModelProviders } = useProviderContext()
|
||||
const refreshModelProviders = useProviderContextSelector(state => state.refreshModelProviders)
|
||||
const currentProviderName = provider.provider
|
||||
const expanded = useModelProviderListExpanded(currentProviderName)
|
||||
const setExpanded = useSetModelProviderListExpanded(currentProviderName)
|
||||
@ -183,4 +183,4 @@ const ProviderAddedCard: FC<ProviderAddedCardProps> = ({
|
||||
)
|
||||
}
|
||||
|
||||
export default ProviderAddedCard
|
||||
export default memo(ProviderAddedCard)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import type { UsagePriority } from '../use-credential-panel-state'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/app/components/base/ui/tooltip'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { PreferredProviderTypeEnum } from '../../declarations'
|
||||
|
||||
@ -30,7 +31,20 @@ export default function UsagePrioritySection({ value, disabled, onSelect }: Usag
|
||||
<span className="truncate text-text-secondary system-sm-medium">
|
||||
{t('modelProvider.card.usagePriority', { ns: 'common' })}
|
||||
</span>
|
||||
<span className="i-ri-question-line h-3.5 w-3.5 shrink-0 text-text-quaternary" />
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
aria-label={t('modelProvider.card.usagePriorityTip', { ns: 'common' })}
|
||||
delay={0}
|
||||
render={(
|
||||
<span className="flex h-4 w-4 shrink-0 items-center justify-center">
|
||||
<span aria-hidden className="i-ri-question-line h-3.5 w-3.5 text-text-quaternary hover:text-text-tertiary" />
|
||||
</span>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('modelProvider.card.usagePriorityTip', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-1">
|
||||
{options.map(option => (
|
||||
|
||||
@ -21,7 +21,8 @@ export function useActivateCredential(provider: ModelProvider) {
|
||||
const selectedIdRef = useRef(selectedCredentialId)
|
||||
selectedIdRef.current = selectedCredentialId
|
||||
|
||||
const supportedModelTypes = provider.supported_model_types
|
||||
const supportedModelTypesRef = useRef(provider.supported_model_types)
|
||||
supportedModelTypesRef.current = provider.supported_model_types
|
||||
|
||||
const activate = useCallback((credential: Credential) => {
|
||||
if (credential.credential_id === selectedIdRef.current)
|
||||
@ -33,7 +34,7 @@ export function useActivateCredential(provider: ModelProvider) {
|
||||
onSuccess: () => {
|
||||
Toast.notify({ type: 'success', message: t('api.actionSuccess', { ns: 'common' }) })
|
||||
updateModelProviders()
|
||||
supportedModelTypes.forEach(type => updateModelList(type))
|
||||
supportedModelTypesRef.current.forEach(type => updateModelList(type))
|
||||
},
|
||||
onError: () => {
|
||||
setOptimisticId(undefined)
|
||||
@ -41,7 +42,7 @@ export function useActivateCredential(provider: ModelProvider) {
|
||||
},
|
||||
},
|
||||
)
|
||||
}, [mutate, t, updateModelProviders, updateModelList, supportedModelTypes])
|
||||
}, [mutate, t, updateModelProviders, updateModelList])
|
||||
|
||||
return {
|
||||
selectedCredentialId,
|
||||
|
||||
@ -4672,9 +4672,6 @@
|
||||
}
|
||||
},
|
||||
"app/components/header/account-setting/model-provider-page/hooks.ts": {
|
||||
"react-hooks-extra/no-direct-set-state-in-use-effect": {
|
||||
"count": 1
|
||||
},
|
||||
"ts/no-explicit-any": {
|
||||
"count": 2
|
||||
}
|
||||
|
||||
@ -371,6 +371,7 @@
|
||||
"modelProvider.card.upgradePlan": "upgrade your plan",
|
||||
"modelProvider.card.usageLabel": "Usage",
|
||||
"modelProvider.card.usagePriority": "Usage Priority",
|
||||
"modelProvider.card.usagePriorityTip": "Set which resource to use first when running models.",
|
||||
"modelProvider.collapse": "Collapse",
|
||||
"modelProvider.config": "Config",
|
||||
"modelProvider.configLoadBalancing": "Config Load Balancing",
|
||||
|
||||
@ -353,6 +353,7 @@
|
||||
"modelProvider.card.removeKey": "API キーを削除",
|
||||
"modelProvider.card.tip": "メッセージ枠は{{modelNames}}のモデルを使用することをサポートしています。無料枠は有料枠が使い果たされた後に消費されます。",
|
||||
"modelProvider.card.tokens": "トークン",
|
||||
"modelProvider.card.usagePriorityTip": "モデル実行時に優先して使用するリソースを設定します。",
|
||||
"modelProvider.collapse": "折り畳み",
|
||||
"modelProvider.config": "設定",
|
||||
"modelProvider.configLoadBalancing": "負荷分散の設定",
|
||||
|
||||
@ -371,6 +371,7 @@
|
||||
"modelProvider.card.upgradePlan": "升级套餐",
|
||||
"modelProvider.card.usageLabel": "用量",
|
||||
"modelProvider.card.usagePriority": "使用优先级",
|
||||
"modelProvider.card.usagePriorityTip": "设置运行模型时优先使用的资源。",
|
||||
"modelProvider.collapse": "收起",
|
||||
"modelProvider.config": "配置",
|
||||
"modelProvider.configLoadBalancing": "设置负载均衡",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user