diff --git a/frontend/src/components/duplicates/DuplicatesView.tsx b/frontend/src/components/duplicates/DuplicatesView.tsx index 76455bc..b9fc5aa 100644 --- a/frontend/src/components/duplicates/DuplicatesView.tsx +++ b/frontend/src/components/duplicates/DuplicatesView.tsx @@ -180,6 +180,26 @@ export function DuplicatesView() { return () => window.removeEventListener('keydown', onKeyDown) }, [allMemberIds, activePhotoId, columns, selectPhoto, virtualizer]) + // Stable handlers — passed through memoised section + thumbnail so + // React.memo is actually effective. The `discardMutation.mutate` and + // store actions have stable identity already; we wrap them once so the + // closure identity doesn't change per render. Must sit above the early + // returns below — rules of hooks forbid conditional hook calls. + const allMemberIdsRef = useRef(allMemberIds) + allMemberIdsRef.current = allMemberIds + const handleKeepBest = useCallback( + (discardIds: string[]) => discardMutation.mutate(discardIds), + [discardMutation] + ) + const handlePreviewMember = useCallback( + (memberId: string) => openPreview(memberId, allMemberIdsRef.current), + [openPreview] + ) + const handleSelectMember = useCallback( + (memberId: string) => selectPhoto(memberId), + [selectPhoto] + ) + if (isLoading) { return (