Skip to content

Commit 50b3987

Browse files
committed
fix(react): revert unsafe render-time side effects to useEffect
1 parent 3afc09d commit 50b3987

File tree

4 files changed

+53
-38
lines changed

4 files changed

+53
-38
lines changed

apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/document-tags-modal/document-tags-modal.tsx

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

3-
import { useCallback, useMemo, useState } from 'react'
3+
import { useCallback, useEffect, useState } from 'react'
44
import { createLogger } from '@sim/logger'
55
import {
66
Badge,
@@ -20,7 +20,10 @@ import { cn } from '@/lib/core/utils/cn'
2020
import { ALL_TAG_SLOTS, type AllTagSlot, MAX_TAG_SLOTS } from '@/lib/knowledge/constants'
2121
import type { DocumentTag } from '@/lib/knowledge/tags/types'
2222
import type { DocumentData } from '@/lib/knowledge/types'
23-
import { useKnowledgeBaseTagDefinitions } from '@/hooks/kb/use-knowledge-base-tag-definitions'
23+
import {
24+
type TagDefinition,
25+
useKnowledgeBaseTagDefinitions,
26+
} from '@/hooks/kb/use-knowledge-base-tag-definitions'
2427
import { type TagDefinitionInput, useTagDefinitions } from '@/hooks/kb/use-tag-definitions'
2528
import { useNextAvailableSlotMutation, useUpdateDocumentTags } from '@/hooks/queries/kb/knowledge'
2629

@@ -97,6 +100,7 @@ export function DocumentTagsModal({
97100
const { saveTagDefinitions, tagDefinitions, fetchTagDefinitions } = documentTagHook
98101
const { tagDefinitions: kbTagDefinitions, fetchTagDefinitions: refreshTagDefinitions } = kbTagHook
99102

103+
const [documentTags, setDocumentTags] = useState<DocumentTag[]>([])
100104
const [editingTagIndex, setEditingTagIndex] = useState<number | null>(null)
101105
const [isCreatingTag, setIsCreatingTag] = useState(false)
102106
const [isSavingTag, setIsSavingTag] = useState(false)
@@ -106,13 +110,12 @@ export function DocumentTagsModal({
106110
value: '',
107111
})
108112

109-
const documentTags = useMemo(() => {
110-
if (!documentData || !tagDefinitions) return []
111-
113+
const buildDocumentTags = useCallback((docData: DocumentData, definitions: TagDefinition[]) => {
112114
const tags: DocumentTag[] = []
115+
113116
ALL_TAG_SLOTS.forEach((slot) => {
114-
const rawValue = documentData[slot]
115-
const definition = tagDefinitions.find((def) => def.tagSlot === slot)
117+
const rawValue = docData[slot]
118+
const definition = definitions.find((def) => def.tagSlot === slot)
116119

117120
if (rawValue !== null && rawValue !== undefined && definition) {
118121
const stringValue = String(rawValue).trim()
@@ -128,7 +131,11 @@ export function DocumentTagsModal({
128131
})
129132

130133
return tags
131-
}, [documentData, tagDefinitions])
134+
}, [])
135+
136+
const handleTagsChange = useCallback((newTags: DocumentTag[]) => {
137+
setDocumentTags(newTags)
138+
}, [])
132139

133140
const handleSaveDocumentTags = useCallback(
134141
async (tagsToSave: DocumentTag[]) => {
@@ -166,6 +173,7 @@ export function DocumentTagsModal({
166173

167174
const handleRemoveTag = async (index: number) => {
168175
const updatedTags = documentTags.filter((_, i) => i !== index)
176+
handleTagsChange(updatedTags)
169177

170178
try {
171179
await handleSaveDocumentTags(updatedTags)
@@ -276,6 +284,8 @@ export function DocumentTagsModal({
276284
updatedTags = [...documentTags, newTag]
277285
}
278286

287+
handleTagsChange(updatedTags)
288+
279289
if (currentEditingIndex !== null && originalTag) {
280290
const currentDefinition = kbTagDefinitions.find(
281291
(def) => def.displayName.toLowerCase() === originalTag.displayName.toLowerCase()
@@ -351,6 +361,13 @@ export function DocumentTagsModal({
351361

352362
const canAddNewTag = kbTagDefinitions.length < MAX_TAG_SLOTS || availableDefinitions.length > 0
353363

364+
useEffect(() => {
365+
if (documentData && tagDefinitions && !isSavingTag) {
366+
const rebuiltTags = buildDocumentTags(documentData, tagDefinitions)
367+
setDocumentTags(rebuiltTags)
368+
}
369+
}, [documentData, tagDefinitions, buildDocumentTags, isSavingTag])
370+
354371
const handleClose = (openState: boolean) => {
355372
if (!openState) {
356373
setIsCreatingTag(false)

apps/sim/app/workspace/[workspaceId]/settings/hooks/use-profile-picture-upload.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ export function useProfilePictureUpload({
2626
const [fileName, setFileName] = useState<string | null>(null)
2727
const [isUploading, setIsUploading] = useState(false)
2828

29-
const prevCurrentImageRef = useRef(currentImage)
30-
if (currentImage !== prevCurrentImageRef.current) {
31-
prevCurrentImageRef.current = currentImage
32-
if (previewRef.current && previewRef.current !== currentImage) {
33-
URL.revokeObjectURL(previewRef.current)
34-
previewRef.current = null
29+
useEffect(() => {
30+
if (currentImage !== previewUrl) {
31+
if (previewRef.current && previewRef.current !== currentImage) {
32+
URL.revokeObjectURL(previewRef.current)
33+
previewRef.current = null
34+
}
35+
setPreviewUrl(currentImage || null)
3536
}
36-
setPreviewUrl(currentImage || null)
37-
}
37+
}, [currentImage, previewUrl])
3838

3939
const validateFile = useCallback((file: File): string | null => {
4040
if (file.size > MAX_FILE_SIZE) {

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,16 @@ export const Sidebar = memo(function Sidebar() {
641641
setIsTaskDeleteModalOpen(true)
642642
}, [tasks])
643643

644+
const navigateToPage = useCallback(
645+
(path: string) => {
646+
if (!isCollapsed) {
647+
setSidebarWidth(SIDEBAR_WIDTH.MIN)
648+
}
649+
router.push(path)
650+
},
651+
[isCollapsed, setSidebarWidth, router]
652+
)
653+
644654
const handleConfirmDeleteTasks = useCallback(() => {
645655
const { taskIds: taskIdsToDelete } = contextMenuSelectionRef.current
646656
if (taskIdsToDelete.length === 0) return
@@ -663,7 +673,7 @@ export const Sidebar = memo(function Sidebar() {
663673
deleteTasksMutation.mutate(taskIdsToDelete, { onSuccess: onDeleteSuccess })
664674
}
665675
setIsTaskDeleteModalOpen(false)
666-
}, [pathname, workspaceId, deleteTaskMutation, deleteTasksMutation, router])
676+
}, [pathname, workspaceId, deleteTaskMutation, deleteTasksMutation, navigateToPage])
667677

668678
const [visibleTaskCount, setVisibleTaskCount] = useState(5)
669679
const [renamingTaskId, setRenamingTaskId] = useState<string | null>(null)
@@ -772,19 +782,11 @@ export const Sidebar = memo(function Sidebar() {
772782
})
773783
}, [workflowId, workflowsLoading])
774784

775-
/**
776-
* Navigates to a non-workflow page and resets the sidebar width to minimum
777-
* when the sidebar is expanded.
778-
*/
779-
const navigateToPage = useCallback(
780-
(path: string) => {
781-
if (!isCollapsed) {
782-
setSidebarWidth(SIDEBAR_WIDTH.MIN)
783-
}
784-
router.push(path)
785-
},
786-
[isCollapsed, setSidebarWidth, router]
787-
)
785+
useEffect(() => {
786+
if (!isOnWorkflowPage && !isCollapsed) {
787+
setSidebarWidth(SIDEBAR_WIDTH.MIN)
788+
}
789+
}, [isOnWorkflowPage, isCollapsed, setSidebarWidth])
788790

789791
const handleCreateWorkflow = useCallback(async () => {
790792
const workflowId = await createWorkflow()

apps/sim/components/emcn/components/code/code.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -869,11 +869,9 @@ const VirtualizedViewerInner = memo(function VirtualizedViewerInner({
869869
return { matchOffsets: offsets, matchCount: cumulative }
870870
}, [lines.length, displayLines, visibleLineIndices, searchQuery])
871871

872-
const prevMatchCountRef = useRef(matchCount)
873-
if (prevMatchCountRef.current !== matchCount) {
874-
prevMatchCountRef.current = matchCount
872+
useEffect(() => {
875873
onMatchCountChange?.(matchCount)
876-
}
874+
}, [matchCount, onMatchCountChange])
877875

878876
// Only process visible lines for efficiency (not all lines)
879877
const visibleLines = useMemo(() => {
@@ -1064,11 +1062,9 @@ const ViewerInner = memo(function ViewerInner({
10641062
return { cumulativeMatches: cumulative, matchCount: cumulative[cumulative.length - 1] }
10651063
}, [lines.length, displayLines, visibleLineIndices, searchQuery])
10661064

1067-
const prevMatchCountRef = useRef(matchCount)
1068-
if (prevMatchCountRef.current !== matchCount) {
1069-
prevMatchCountRef.current = matchCount
1065+
useEffect(() => {
10701066
onMatchCountChange?.(matchCount)
1071-
}
1067+
}, [matchCount, onMatchCountChange])
10721068

10731069
// Pre-compute highlighted lines with search for visible indices (for gutter mode)
10741070
const highlightedVisibleLines = useMemo(() => {

0 commit comments

Comments
 (0)