From 04f85b0ff2f0af7a994cc02736bb87372b02ed2d Mon Sep 17 00:00:00 2001 From: yyh Date: Sun, 18 Jan 2026 01:00:34 +0800 Subject: [PATCH] refactor(web): defer state reads to usage point for Zustand stores Apply "defer state reads to usage point" principle to fix real anti-patterns where state properties were subscribed but only used in callbacks, not in JSX render: - env-panel/variable-modal.tsx: envList, envSecrets -> getState() - chat-variable-panel/variable-modal.tsx: varList -> getState() - publish-as-knowledge-pipeline-modal.tsx: knowledgeName, knowledgeIcon -> lazy useState initialization with getState() - rag-pipeline-header/index.tsx: remove unused showDebugAndPreviewPanel subscription and dead code cleanup --- .../components/publish-as-knowledge-pipeline-modal.tsx | 9 ++++----- .../components/rag-pipeline-header/index.tsx | 5 +---- .../chat-variable-panel/components/variable-modal.tsx | 5 +++-- .../workflow/panel/env-panel/variable-modal.tsx | 9 +++++---- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/web/app/components/rag-pipeline/components/publish-as-knowledge-pipeline-modal.tsx b/web/app/components/rag-pipeline/components/publish-as-knowledge-pipeline-modal.tsx index c981eb9a21..3b902639ce 100644 --- a/web/app/components/rag-pipeline/components/publish-as-knowledge-pipeline-modal.tsx +++ b/web/app/components/rag-pipeline/components/publish-as-knowledge-pipeline-modal.tsx @@ -11,7 +11,7 @@ import Button from '@/app/components/base/button' import Input from '@/app/components/base/input' import Modal from '@/app/components/base/modal' import Textarea from '@/app/components/base/textarea' -import { useStore } from '@/app/components/workflow/store' +import { useWorkflowStore } from '@/app/components/workflow/store' type PublishAsKnowledgePipelineModalProps = { confirmDisabled?: boolean @@ -28,10 +28,9 @@ const PublishAsKnowledgePipelineModal = ({ onConfirm, }: PublishAsKnowledgePipelineModalProps) => { const { t } = useTranslation() - const knowledgeName = useStore(s => s.knowledgeName) - const knowledgeIcon = useStore(s => s.knowledgeIcon) - const [pipelineName, setPipelineName] = useState(knowledgeName!) - const [pipelineIcon, setPipelineIcon] = useState(knowledgeIcon!) + const workflowStore = useWorkflowStore() + const [pipelineName, setPipelineName] = useState(() => workflowStore.getState().knowledgeName!) + const [pipelineIcon, setPipelineIcon] = useState(() => workflowStore.getState().knowledgeIcon!) const [description, setDescription] = useState('') const [showAppIconPicker, setShowAppIconPicker] = useState(false) diff --git a/web/app/components/rag-pipeline/components/rag-pipeline-header/index.tsx b/web/app/components/rag-pipeline/components/rag-pipeline-header/index.tsx index fe2490f281..a12edaa46d 100644 --- a/web/app/components/rag-pipeline/components/rag-pipeline-header/index.tsx +++ b/web/app/components/rag-pipeline/components/rag-pipeline-header/index.tsx @@ -3,7 +3,6 @@ import { memo, useMemo, } from 'react' -import { useTranslation } from 'react-i18next' import Header from '@/app/components/workflow/header' import { useStore, @@ -13,9 +12,7 @@ import Publisher from './publisher' import RunMode from './run-mode' const RagPipelineHeader = () => { - const { t } = useTranslation() const pipelineId = useStore(s => s.pipelineId) - const showDebugAndPreviewPanel = useStore(s => s.showDebugAndPreviewPanel) const viewHistoryProps = useMemo(() => { return { @@ -42,7 +39,7 @@ const RagPipelineHeader = () => { viewHistoryProps, }, } - }, [viewHistoryProps, showDebugAndPreviewPanel, t]) + }, [viewHistoryProps]) return (
diff --git a/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx b/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx index 18c3cb7941..5c07cca3df 100644 --- a/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx +++ b/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx @@ -22,7 +22,7 @@ import { arrayStringPlaceholder, objectPlaceholder, } from '@/app/components/workflow/panel/chat-variable-panel/utils' -import { useStore } from '@/app/components/workflow/store' +import { useWorkflowStore } from '@/app/components/workflow/store' import { cn } from '@/utils/classnames' import { checkKeys, replaceSpaceWithUnderscoreInVarNameInput } from '@/utils/var' import ArrayBoolList from './array-bool-list' @@ -58,7 +58,7 @@ const ChatVariableModal = ({ }: ModalPropsType) => { const { t } = useTranslation() const { notify } = useContext(ToastContext) - const varList = useStore(s => s.conversationVariables) + const workflowStore = useWorkflowStore() const [name, setName] = React.useState('') const [type, setType] = React.useState(ChatVarType.String) const [value, setValue] = React.useState() @@ -234,6 +234,7 @@ const ChatVariableModal = ({ const handleSave = () => { if (!checkVariableName(name)) return + const varList = workflowStore.getState().conversationVariables if (!chatVar && varList.some(chatVar => chatVar.name === name)) return notify({ type: 'error', message: 'name is existed' }) // if (type !== ChatVarType.Object && !value) diff --git a/web/app/components/workflow/panel/env-panel/variable-modal.tsx b/web/app/components/workflow/panel/env-panel/variable-modal.tsx index 41b91211f0..0e120ac77c 100644 --- a/web/app/components/workflow/panel/env-panel/variable-modal.tsx +++ b/web/app/components/workflow/panel/env-panel/variable-modal.tsx @@ -9,7 +9,7 @@ import Button from '@/app/components/base/button' import Input from '@/app/components/base/input' import { ToastContext } from '@/app/components/base/toast' import Tooltip from '@/app/components/base/tooltip' -import { useStore } from '@/app/components/workflow/store' +import { useWorkflowStore } from '@/app/components/workflow/store' import { cn } from '@/utils/classnames' import { checkKeys, replaceSpaceWithUnderscoreInVarNameInput } from '@/utils/var' @@ -25,8 +25,7 @@ const VariableModal = ({ }: ModalPropsType) => { const { t } = useTranslation() const { notify } = useContext(ToastContext) - const envList = useStore(s => s.environmentVariables) - const envSecrets = useStore(s => s.envSecrets) + const workflowStore = useWorkflowStore() const [type, setType] = React.useState<'string' | 'number' | 'secret'>('string') const [name, setName] = React.useState('') const [value, setValue] = React.useState() @@ -58,6 +57,7 @@ const VariableModal = ({ return notify({ type: 'error', message: 'value can not be empty' }) // Add check for duplicate name when editing + const envList = workflowStore.getState().environmentVariables if (env && env.name !== name && envList.some(e => e.name === name)) return notify({ type: 'error', message: 'name is existed' }) // Original check for create new variable @@ -78,10 +78,11 @@ const VariableModal = ({ if (env) { setType(env.value_type) setName(env.name) + const envSecrets = workflowStore.getState().envSecrets setValue(env.value_type === 'secret' ? envSecrets[env.id] : env.value) setDescription(env.description) } - }, [env, envSecrets]) + }, [env, workflowStore]) return (