fix(duplicates): hoist memo hooks above early returns
Rules-of-hooks violation: useRef and three useCallbacks sat after the isLoading/isError/empty early-return block, so first render (loading) called N hooks and the post-data render called N+4, crashing the view. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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 (
|
||||
<div className="flex h-full items-center justify-center text-text-muted">
|
||||
@@ -211,25 +231,6 @@ export function DuplicatesView() {
|
||||
)
|
||||
}
|
||||
|
||||
// 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.
|
||||
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]
|
||||
)
|
||||
|
||||
return (
|
||||
<div ref={scrollRef} className="h-full overflow-auto bg-bg p-4 pb-20">
|
||||
<div className="mb-4 flex items-center gap-2 text-xs text-text-muted">
|
||||
|
||||
Reference in New Issue
Block a user