fix: prevent empty workflow draft sync during page navigation (#25140)

This commit is contained in:
lyzno1
2025-09-04 17:13:49 +08:00
committed by GitHub
parent 83fab4bc19
commit 1fffc79c32
4 changed files with 25 additions and 7 deletions

View File

@@ -33,19 +33,15 @@ export const useNodesSyncDraft = () => {
conversationVariables,
environmentVariables,
syncWorkflowDraftHash,
isWorkflowDataLoaded,
} = workflowStore.getState()
if (appId) {
const nodes = getNodes()
// Prevent syncing empty workflow if React Flow isn't properly initialized
// Check multiple indicators of uninitialized state:
// 1. Empty nodes with default viewport (x=0, y=0, zoom=1)
// 2. Empty edges array along with empty nodes
if (nodes.length === 0 && edges.length === 0 && x === 0 && y === 0 && zoom === 1) {
// This appears to be an uninitialized React Flow state, skip sync to prevent data loss
// Prevent sync if workflow data hasn't been loaded yet
if (!isWorkflowDataLoaded)
return null
}
const features = featuresStore!.getState().features
const producedNodes = produce(nodes, (draft) => {

View File

@@ -49,6 +49,7 @@ export const useWorkflowInit = () => {
}, {} as Record<string, string>),
environmentVariables: res.environment_variables?.map(env => env.value_type === 'secret' ? { ...env, value: '[__HIDDEN__]' } : env) || [],
conversationVariables: res.conversation_variables || [],
isWorkflowDataLoaded: true,
})
setSyncWorkflowDraftHash(res.hash)
setIsLoading(false)

View File

@@ -1,6 +1,7 @@
'use client'
import {
useEffect,
useMemo,
} from 'react'
import useSWR from 'swr'
@@ -10,6 +11,7 @@ import {
import {
useWorkflowInit,
} from './hooks'
import { useWorkflowStore } from '@/app/components/workflow/store'
import {
initialEdges,
initialNodes,
@@ -32,9 +34,24 @@ const WorkflowAppWithAdditionalContext = () => {
data,
isLoading,
} = useWorkflowInit()
const workflowStore = useWorkflowStore()
const { isLoadingCurrentWorkspace, currentWorkspace } = useAppContext()
const { data: fileUploadConfigResponse } = useSWR({ url: '/files/upload' }, fetchFileUploadConfig)
// Cleanup on unmount
useEffect(() => {
return () => {
// Reset the loaded flag when component unmounts
workflowStore.setState({ isWorkflowDataLoaded: false })
// Cancel any pending debounced sync operations
const { debouncedSyncWorkflowDraft } = workflowStore.getState()
// The debounced function from lodash has a cancel method
if (debouncedSyncWorkflowDraft && 'cancel' in debouncedSyncWorkflowDraft)
(debouncedSyncWorkflowDraft as any).cancel()
}
}, [workflowStore])
const nodesData = useMemo(() => {
if (data)
return initialNodes(data.graph.nodes, data.graph.edges)

View File

@@ -21,6 +21,8 @@ export type WorkflowDraftSliceShape = {
setSyncWorkflowDraftHash: (hash: string) => void
isSyncingWorkflowDraft: boolean
setIsSyncingWorkflowDraft: (isSyncingWorkflowDraft: boolean) => void
isWorkflowDataLoaded: boolean
setIsWorkflowDataLoaded: (loaded: boolean) => void
}
export const createWorkflowDraftSlice: StateCreator<WorkflowDraftSliceShape> = set => ({
@@ -33,4 +35,6 @@ export const createWorkflowDraftSlice: StateCreator<WorkflowDraftSliceShape> = s
setSyncWorkflowDraftHash: syncWorkflowDraftHash => set(() => ({ syncWorkflowDraftHash })),
isSyncingWorkflowDraft: false,
setIsSyncingWorkflowDraft: isSyncingWorkflowDraft => set(() => ({ isSyncingWorkflowDraft })),
isWorkflowDataLoaded: false,
setIsWorkflowDataLoaded: loaded => set(() => ({ isWorkflowDataLoaded: loaded })),
})