refactor: hook dependencies name everything the hooks read
The 12 react-hooks/exhaustive-deps warnings the gate let through: - ShareDialog and YearFilter built a fresh [] per render while their query loaded, so their memos recomputed on every render; they share one empty list now. - VideoEditor's drag effect called a seek/moveBoundary recreated each render; both are stable callbacks in its deps. - WizardProvider re-checks onboarding on exactly the fields it reads (not the me object, whose 60 s refetch would reopen a closed wizard). - Channels, Feed and PlexPlayer list the stable values they already used. - The player's keydown effect is bound once on purpose (its helpers read refs): said so, with a disable, as the codebase's other deliberate sites do. - dialogFocus and the YouTube player's cleanup read refs React may already have let go of; they use what they captured when the effect ran.
This commit is contained in:
@@ -130,10 +130,13 @@ export default function VideoEditor({ job, onClose }: { job: DownloadJob; onClos
|
||||
const v = videoRef.current;
|
||||
if (v) setCurrent(v.currentTime);
|
||||
};
|
||||
const seek = (s: number) => {
|
||||
const v = videoRef.current;
|
||||
if (v) v.currentTime = Math.max(0, Math.min(duration, s));
|
||||
};
|
||||
const seek = useCallback(
|
||||
(s: number) => {
|
||||
const v = videoRef.current;
|
||||
if (v) v.currentTime = Math.max(0, Math.min(duration, s));
|
||||
},
|
||||
[duration],
|
||||
);
|
||||
const playPause = () => {
|
||||
const v = videoRef.current;
|
||||
if (!v) return;
|
||||
@@ -154,18 +157,21 @@ export default function VideoEditor({ job, onClose }: { job: DownloadJob; onClos
|
||||
return next;
|
||||
});
|
||||
};
|
||||
const moveBoundary = (bi: number, time: number) =>
|
||||
setSegments((segs) => {
|
||||
if (creating.current || bi < 0 || bi >= segs.length - 1) return segs;
|
||||
// bi is in [0, length-2] here, so bi and bi+1 both index existing segments.
|
||||
const lo = segs[bi]!.start + MIN_SEG;
|
||||
const hi = segs[bi + 1]!.end - MIN_SEG;
|
||||
const tt = Math.max(lo, Math.min(hi, time));
|
||||
const copy = [...segs];
|
||||
copy[bi] = { ...copy[bi]!, end: tt };
|
||||
copy[bi + 1] = { ...copy[bi + 1]!, start: tt };
|
||||
return copy;
|
||||
});
|
||||
const moveBoundary = useCallback(
|
||||
(bi: number, time: number) =>
|
||||
setSegments((segs) => {
|
||||
if (creating.current || bi < 0 || bi >= segs.length - 1) return segs;
|
||||
// bi is in [0, length-2] here, so bi and bi+1 both index existing segments.
|
||||
const lo = segs[bi]!.start + MIN_SEG;
|
||||
const hi = segs[bi + 1]!.end - MIN_SEG;
|
||||
const tt = Math.max(lo, Math.min(hi, time));
|
||||
const copy = [...segs];
|
||||
copy[bi] = { ...copy[bi]!, end: tt };
|
||||
copy[bi + 1] = { ...copy[bi + 1]!, start: tt };
|
||||
return copy;
|
||||
}),
|
||||
[],
|
||||
);
|
||||
const deleteBoundary = (bi: number) =>
|
||||
setSegments((segs) => {
|
||||
if (creating.current || segs.length < 2) return segs;
|
||||
@@ -205,7 +211,7 @@ export default function VideoEditor({ job, onClose }: { job: DownloadJob; onClos
|
||||
window.removeEventListener("pointermove", move);
|
||||
window.removeEventListener("pointerup", up);
|
||||
};
|
||||
}, [drag, timeAt]);
|
||||
}, [drag, timeAt, seek, moveBoundary]);
|
||||
|
||||
// --- crop drag ---
|
||||
const overlayRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
Reference in New Issue
Block a user