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:
2026-09-17 02:45:19 +02:00
parent 5883ea509d
commit 569190480d
10 changed files with 66 additions and 32 deletions
+3 -1
View File
@@ -441,6 +441,8 @@ export function useYtProgress({
});
});
// The session's positions map (mutated in place, never replaced) — held here for the cleanup.
const sessionPos = sessionPosRef.current;
// Periodic checkpoint so progress (and auto-watch) survive a crash/refresh.
const timer = window.setInterval(persist, 5000);
// Save on page unload too (F5/close/navigate): effect cleanup doesn't run on a full reload. A
@@ -469,7 +471,7 @@ export function useYtProgress({
// not enough on its own: nothing refetches the feed until it remounts (staleTime 30s,
// refetchOnWindowFocus off), so a reopen used to resume from the position the cache was
// fetched with — and the next checkpoint then persisted that older value over this one.
patchCachedProgress(qc, sessionPosRef.current);
patchCachedProgress(qc, sessionPos);
qc.invalidateQueries({ queryKey: qk.feed(), refetchType: "none" });
qc.invalidateQueries({ queryKey: qk.playlist(), refetchType: "none" });
});