Skip to content

Commit 7a5aead

Browse files
Vikhyath MondretiVikhyath Mondreti
authored andcommitted
fix(knowledge base): selector infinite render
1 parent f4e627a commit 7a5aead

File tree

6 files changed

+76
-170
lines changed

6 files changed

+76
-170
lines changed

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/document-selector/document-selector.tsx

Lines changed: 20 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { useCallback, useEffect, useState } from 'react'
3+
import { useCallback, useEffect, useMemo, useState } from 'react'
44
import { Check, ChevronDown, FileText } from 'lucide-react'
55
import { Button } from '@/components/ui/button'
66
import {
@@ -13,8 +13,8 @@ import {
1313
} from '@/components/ui/command'
1414
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
1515
import type { SubBlockConfig } from '@/blocks/types'
16-
import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow'
1716
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
17+
import { useSubBlockValue } from '../../hooks/use-sub-block-value'
1818

1919
interface DocumentData {
2020
id: string
@@ -52,38 +52,23 @@ export function DocumentSelector({
5252
previewValue,
5353
}: DocumentSelectorProps) {
5454
const { getValue } = useSubBlockStore()
55-
const { collaborativeSetSubblockValue } = useCollaborativeWorkflow()
5655

5756
const [documents, setDocuments] = useState<DocumentData[]>([])
5857
const [error, setError] = useState<string | null>(null)
5958
const [open, setOpen] = useState(false)
6059
const [selectedDocument, setSelectedDocument] = useState<DocumentData | null>(null)
6160
const [initialFetchDone, setInitialFetchDone] = useState(false)
62-
const [selectedId, setSelectedId] = useState('')
6361

64-
// Get the current value from the store
65-
const storeValue = getValue(blockId, subBlock.id)
62+
// Use the proper hook to get the current value and setter
63+
const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlock.id)
6664

67-
// Get the knowledge base ID from the same block's knowledgeBaseId subblock
68-
const knowledgeBaseId = getValue(blockId, 'knowledgeBaseId')
65+
// Get the knowledge base ID from the same block's knowledgeBaseId subblock - memoize to prevent re-renders
66+
const knowledgeBaseId = useMemo(() => getValue(blockId, 'knowledgeBaseId'), [getValue, blockId])
6967

7068
// Use preview value when in preview mode, otherwise use store value
7169
const value = isPreview ? previewValue : storeValue
7270

73-
// Initialize selectedId with the effective value
74-
useEffect(() => {
75-
if (isPreview && previewValue !== undefined) {
76-
setSelectedId(previewValue || '')
77-
} else {
78-
setSelectedId(value || '')
79-
}
80-
}, [value, isPreview, previewValue])
8171

82-
// Update local state when external value changes
83-
useEffect(() => {
84-
const currentValue = isPreview ? previewValue : value
85-
setSelectedId(currentValue || '')
86-
}, [value, isPreview, previewValue])
8772

8873
// Fetch documents for the selected knowledge base
8974
const fetchDocuments = useCallback(async () => {
@@ -112,46 +97,12 @@ export function DocumentSelector({
11297
const fetchedDocuments = result.data || []
11398
setDocuments(fetchedDocuments)
11499
setInitialFetchDone(true)
115-
116-
// Auto-selection logic: if we have a valid selection, keep it
117-
// If there's only one document, select it
118-
// If we have a value but it's not in the documents, reset it
119-
if (selectedId && !fetchedDocuments.some((doc: DocumentData) => doc.id === selectedId)) {
120-
setSelectedId('')
121-
if (!isPreview) {
122-
collaborativeSetSubblockValue(blockId, subBlock.id, '')
123-
}
124-
}
125-
126-
if (
127-
(!selectedId || !fetchedDocuments.some((doc: DocumentData) => doc.id === selectedId)) &&
128-
fetchedDocuments.length > 0
129-
) {
130-
if (fetchedDocuments.length === 1) {
131-
// If only one document, auto-select it
132-
const singleDoc = fetchedDocuments[0]
133-
setSelectedId(singleDoc.id)
134-
setSelectedDocument(singleDoc)
135-
if (!isPreview) {
136-
collaborativeSetSubblockValue(blockId, subBlock.id, singleDoc.id)
137-
}
138-
onDocumentSelect?.(singleDoc.id)
139-
}
140-
}
141100
} catch (err) {
142101
if ((err as Error).name === 'AbortError') return
143102
setError((err as Error).message)
144103
setDocuments([])
145104
}
146-
}, [
147-
knowledgeBaseId,
148-
selectedId,
149-
collaborativeSetSubblockValue,
150-
blockId,
151-
subBlock.id,
152-
isPreview,
153-
onDocumentSelect,
154-
])
105+
}, [knowledgeBaseId])
155106

156107
// Handle dropdown open/close - fetch documents when opening
157108
const handleOpenChange = (isOpen: boolean) => {
@@ -170,50 +121,35 @@ export function DocumentSelector({
170121
if (isPreview) return
171122

172123
setSelectedDocument(document)
173-
setSelectedId(document.id)
174-
175-
if (!isPreview) {
176-
collaborativeSetSubblockValue(blockId, subBlock.id, document.id)
177-
}
178-
124+
setStoreValue(document.id)
179125
onDocumentSelect?.(document.id)
180126
setOpen(false)
181127
}
182128

183129
// Sync selected document with value prop
184130
useEffect(() => {
185-
if (selectedId && documents.length > 0) {
186-
const docInfo = documents.find((doc) => doc.id === selectedId)
187-
if (docInfo) {
188-
setSelectedDocument(docInfo)
189-
} else {
190-
setSelectedDocument(null)
191-
}
192-
} else if (!selectedId) {
131+
if (value && documents.length > 0) {
132+
const docInfo = documents.find((doc) => doc.id === value)
133+
setSelectedDocument(docInfo || null)
134+
} else {
193135
setSelectedDocument(null)
194136
}
195-
}, [selectedId, documents])
137+
}, [value, documents])
196138

197139
// Reset documents when knowledge base changes
198140
useEffect(() => {
199-
if (knowledgeBaseId) {
200-
setDocuments([])
201-
setSelectedDocument(null)
202-
setSelectedId('')
203-
setInitialFetchDone(false)
204-
setError(null)
205-
if (!isPreview) {
206-
collaborativeSetSubblockValue(blockId, subBlock.id, '')
207-
}
208-
}
209-
}, [knowledgeBaseId, blockId, subBlock.id, collaborativeSetSubblockValue, isPreview])
141+
setDocuments([])
142+
setSelectedDocument(null)
143+
setInitialFetchDone(false)
144+
setError(null)
145+
}, [knowledgeBaseId])
210146

211147
// Fetch documents when knowledge base is available and we haven't fetched yet
212148
useEffect(() => {
213149
if (knowledgeBaseId && !initialFetchDone && !isPreview) {
214150
fetchDocuments()
215151
}
216-
}, [knowledgeBaseId, initialFetchDone, fetchDocuments, isPreview])
152+
}, [knowledgeBaseId, initialFetchDone, isPreview])
217153

218154
const formatDocumentName = (document: DocumentData) => {
219155
return document.filename
@@ -307,7 +243,7 @@ export function DocumentSelector({
307243
</div>
308244
</div>
309245
</div>
310-
{document.id === selectedId && <Check className='ml-auto h-4 w-4' />}
246+
{document.id === value && <Check className='ml-auto h-4 w-4' />}
311247
</CommandItem>
312248
))}
313249
</CommandGroup>

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { SubBlockConfig } from '@/blocks/types'
77
import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow'
88
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
99
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
10+
import { useSubBlockValue } from '../../hooks/use-sub-block-value'
1011
import type { ConfluenceFileInfo } from './components/confluence-file-selector'
1112
import { ConfluenceFileSelector } from './components/confluence-file-selector'
1213
import type { DiscordChannelInfo } from './components/discord-channel-selector'
@@ -40,6 +41,9 @@ export function FileSelectorInput({
4041
const { getValue } = useSubBlockStore()
4142
const { collaborativeSetSubblockValue } = useCollaborativeWorkflow()
4243
const { activeWorkflowId } = useWorkflowRegistry()
44+
45+
// Use the proper hook to get the current value and setter
46+
const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlock.id)
4347
const [selectedFileId, setSelectedFileId] = useState<string>('')
4448
const [_fileInfo, setFileInfo] = useState<FileInfo | ConfluenceFileInfo | null>(null)
4549
const [selectedIssueId, setSelectedIssueId] = useState<string>('')
@@ -66,7 +70,7 @@ export function FileSelectorInput({
6670
const serverId = isDiscord ? (getValue(blockId, 'serverId') as string) || '' : ''
6771

6872
// Use preview value when in preview mode, otherwise use store value
69-
const value = isPreview ? previewValue : getValue(blockId, subBlock.id)
73+
const value = isPreview ? previewValue : storeValue
7074

7175
// Get the current value from the store or prop value if in preview mode
7276
useEffect(() => {
@@ -117,14 +121,14 @@ export function FileSelectorInput({
117121
const handleFileChange = (fileId: string, info?: any) => {
118122
setSelectedFileId(fileId)
119123
setFileInfo(info || null)
120-
collaborativeSetSubblockValue(blockId, subBlock.id, fileId)
124+
setStoreValue(fileId)
121125
}
122126

123127
// Handle issue selection
124128
const handleIssueChange = (issueKey: string, info?: JiraIssueInfo) => {
125129
setSelectedIssueId(issueKey)
126130
setIssueInfo(info || null)
127-
collaborativeSetSubblockValue(blockId, subBlock.id, issueKey)
131+
setStoreValue(issueKey)
128132

129133
// Clear the fields when a new issue is selected
130134
if (isJira) {
@@ -137,14 +141,14 @@ export function FileSelectorInput({
137141
const handleChannelChange = (channelId: string, info?: DiscordChannelInfo) => {
138142
setSelectedChannelId(channelId)
139143
setChannelInfo(info || null)
140-
collaborativeSetSubblockValue(blockId, subBlock.id, channelId)
144+
setStoreValue(channelId)
141145
}
142146

143147
// Handle calendar selection
144148
const handleCalendarChange = (calendarId: string, info?: GoogleCalendarInfo) => {
145149
setSelectedCalendarId(calendarId)
146150
setCalendarInfo(info || null)
147-
collaborativeSetSubblockValue(blockId, subBlock.id, calendarId)
151+
setStoreValue(calendarId)
148152
}
149153

150154
// For Google Drive

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-upload.tsx

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { useRef, useState } from 'react'
44
import { X } from 'lucide-react'
55
import { Button } from '@/components/ui/button'
66
import { Progress } from '@/components/ui/progress'
7-
import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow'
87
import { useNotificationStore } from '@/stores/notifications/store'
98
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
109
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
@@ -58,7 +57,6 @@ export function FileUpload({
5857
// Stores
5958
const { addNotification } = useNotificationStore()
6059
const { activeWorkflowId } = useWorkflowRegistry()
61-
const { collaborativeSetSubblockValue } = useCollaborativeWorkflow()
6260

6361
// Use preview value when in preview mode, otherwise use store value
6462
const value = isPreview ? previewValue : storeValue
@@ -298,16 +296,10 @@ export function FileUpload({
298296
const newFiles = Array.from(uniqueFiles.values())
299297

300298
setStoreValue(newFiles)
301-
302-
// Use collaborative update for persistence
303-
collaborativeSetSubblockValue(blockId, subBlockId, newFiles)
304299
useWorkflowStore.getState().triggerUpdate()
305300
} else {
306301
// For single file: Replace with last uploaded file
307302
setStoreValue(uploadedFiles[0] || null)
308-
309-
// Use collaborative update for persistence
310-
collaborativeSetSubblockValue(blockId, subBlockId, uploadedFiles[0] || null)
311303
useWorkflowStore.getState().triggerUpdate()
312304
}
313305
} catch (error) {
@@ -363,19 +355,9 @@ export function FileUpload({
363355
const filesArray = Array.isArray(value) ? value : value ? [value] : []
364356
const updatedFiles = filesArray.filter((f) => f.path !== file.path)
365357
setStoreValue(updatedFiles.length > 0 ? updatedFiles : null)
366-
367-
// Use collaborative update for persistence
368-
collaborativeSetSubblockValue(
369-
blockId,
370-
subBlockId,
371-
updatedFiles.length > 0 ? updatedFiles : null
372-
)
373358
} else {
374359
// For single file: Clear the value
375360
setStoreValue(null)
376-
377-
// Use collaborative update for persistence
378-
collaborativeSetSubblockValue(blockId, subBlockId, null)
379361
}
380362

381363
useWorkflowStore.getState().triggerUpdate()
@@ -416,7 +398,6 @@ export function FileUpload({
416398

417399
// Clear input state immediately for better UX
418400
setStoreValue(null)
419-
collaborativeSetSubblockValue(blockId, subBlockId, null)
420401
useWorkflowStore.getState().triggerUpdate()
421402

422403
if (fileInputRef.current) {

0 commit comments

Comments
 (0)