mirror of
https://github.com/langgenius/dify.git
synced 2026-02-09 23:20:12 -05:00
perf(skill): stabilize useCallback refs and memoize filtered list
Use useRef for batchUpload and emitTreeUpdate to remove unstable dependencies from useCallback, preventing unnecessary memo invalidation on all 16 TemplateCard components. Wrap filtered list in useMemo and replace && conditional with ternary for rendering safety.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import type { SkillTemplateSummary } from './templates/types'
|
||||
import { memo, useCallback, useState } from 'react'
|
||||
import { memo, useCallback, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import { useWorkflowStore } from '@/app/components/workflow/store'
|
||||
@@ -24,7 +24,11 @@ const SkillTemplatesSection = () => {
|
||||
const appId = appDetail?.id || ''
|
||||
const storeApi = useWorkflowStore()
|
||||
const batchUpload = useBatchUpload()
|
||||
const batchUploadRef = useRef(batchUpload)
|
||||
batchUploadRef.current = batchUpload
|
||||
const emitTreeUpdate = useSkillTreeUpdateEmitter()
|
||||
const emitTreeUpdateRef = useRef(emitTreeUpdate)
|
||||
emitTreeUpdateRef.current = emitTreeUpdate
|
||||
|
||||
const handleUse = useCallback(async (summary: SkillTemplateSummary) => {
|
||||
const entry = SKILL_TEMPLATES.find(e => e.id === summary.id)
|
||||
@@ -39,7 +43,7 @@ const SkillTemplatesSection = () => {
|
||||
const children = await entry.loadContent()
|
||||
const uploadData = await buildUploadDataFromTemplate(summary.name, children)
|
||||
|
||||
await batchUpload.mutateAsync({
|
||||
await batchUploadRef.current.mutateAsync({
|
||||
appId,
|
||||
tree: uploadData.tree,
|
||||
files: uploadData.files,
|
||||
@@ -50,7 +54,7 @@ const SkillTemplatesSection = () => {
|
||||
})
|
||||
|
||||
storeApi.getState().setUploadStatus('success')
|
||||
emitTreeUpdate()
|
||||
emitTreeUpdateRef.current()
|
||||
}
|
||||
catch {
|
||||
storeApi.getState().setUploadStatus('partial_error')
|
||||
@@ -58,9 +62,9 @@ const SkillTemplatesSection = () => {
|
||||
finally {
|
||||
setLoadingId(null)
|
||||
}
|
||||
}, [appId, batchUpload, storeApi, emitTreeUpdate])
|
||||
}, [appId, storeApi])
|
||||
|
||||
const filtered = SKILL_TEMPLATES.filter((entry) => {
|
||||
const filtered = useMemo(() => SKILL_TEMPLATES.filter((entry) => {
|
||||
if (searchValue) {
|
||||
const q = searchValue.toLowerCase()
|
||||
return entry.name.toLowerCase().includes(q) || entry.description.toLowerCase().includes(q)
|
||||
@@ -68,7 +72,7 @@ const SkillTemplatesSection = () => {
|
||||
if (activeCategory !== 'all')
|
||||
return entry.tags?.some(tag => tag.toLowerCase() === activeCategory.toLowerCase())
|
||||
return true
|
||||
})
|
||||
}), [searchValue, activeCategory])
|
||||
|
||||
return (
|
||||
<section className="flex flex-col gap-3 px-6 py-2">
|
||||
@@ -95,9 +99,9 @@ const SkillTemplatesSection = () => {
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{loadingId && (
|
||||
<div className="pointer-events-none fixed inset-0 z-50" />
|
||||
)}
|
||||
{loadingId
|
||||
? <div className="pointer-events-none fixed inset-0 z-50" />
|
||||
: null}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user