From 25e59ee695de8534c064f4d0c9c7e6d1fbda9dd9 Mon Sep 17 00:00:00 2001 From: Emir Karabeg Date: Tue, 1 Apr 2025 14:36:58 -0700 Subject: [PATCH] fix: debounce sync on subblock and dropdown zustand load --- .../sub-block/components/dropdown.tsx | 46 +++++++++++++------ .../sub-block/hooks/use-sub-block-value.ts | 2 + sim/stores/workflows/subblock/store.ts | 27 +++++++++++ 3 files changed, 61 insertions(+), 14 deletions(-) diff --git a/sim/app/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx b/sim/app/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx index a5de4ece6e..0c315d3614 100644 --- a/sim/app/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx +++ b/sim/app/w/[id]/components/workflow-block/components/sub-block/components/dropdown.tsx @@ -1,4 +1,4 @@ -import { useEffect, useMemo } from 'react' +import { useMemo } from 'react' import { Select, SelectContent, @@ -18,22 +18,13 @@ interface DropdownProps { } export function Dropdown({ options, defaultValue, blockId, subBlockId }: DropdownProps) { - const [value, setValue] = useSubBlockValue(blockId, subBlockId, true) + const [value, setValue] = useSubBlockValue(blockId, subBlockId, true) // Evaluate options if it's a function const evaluatedOptions = useMemo(() => { return typeof options === 'function' ? options() : options }, [options]) - // Set the value to the first option if it's not set - useEffect(() => { - if (!value && evaluatedOptions.length > 0) { - const firstOption = evaluatedOptions[0] - const firstValue = typeof firstOption === 'string' ? firstOption : firstOption.id - setValue(firstValue) - } - }, [value, evaluatedOptions, defaultValue, setValue]) - const getOptionValue = (option: string | { label: string; id: string }) => { return typeof option === 'string' ? option : option.id } @@ -42,11 +33,38 @@ export function Dropdown({ options, defaultValue, blockId, subBlockId }: Dropdow return typeof option === 'string' ? option : option.label } + // Calculate the effective value to use in the dropdown + // Priority: 1. Stored value (value) > 2. Provided defaultValue > 3. First option + const effectiveValue = useMemo(() => { + // If we have a value from the store, use that + if (value !== null && value !== undefined) { + return value + } + + // Fall back to provided defaultValue + if (defaultValue !== undefined) { + return defaultValue + } + + // Last resort: use first option value if available + if (evaluatedOptions.length > 0) { + return getOptionValue(evaluatedOptions[0]) + } + + // No valid value available + return undefined + }, [value, defaultValue, evaluatedOptions]) + + // Handle the case where evaluatedOptions changes and the current selection is no longer valid + const isValueInOptions = useMemo(() => { + if (!effectiveValue || evaluatedOptions.length === 0) return false + return evaluatedOptions.some((opt) => getOptionValue(opt) === effectiveValue) + }, [effectiveValue, evaluatedOptions]) + return (