Skip to content

Commit aded09b

Browse files
chore(lint): enforce react/exhaustive-effect-dependencies
Co-Authored-By: Claude Opus 5.5 <[email protected]>
1 parent 04a21bb commit aded09b

23 files changed

Lines changed: 50 additions & 13 deletions

‎apps/mobile/src/components/ComposerEditor.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export function ComposerEditor({
7979
() => () => {
8080
importRef.current?.abort();
8181
},
82+
// oxlint-disable-next-line react/exhaustive-effect-dependencies -- Switching drafts aborts an import owned by the previous draft.
8283
[draftKey],
8384
);
8485
const pasteContext = async (

‎apps/mobile/src/components/MediaVideoPlayer.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ function LoadedMediaVideo(props: {
102102
},
103103
);
104104
return () => controller.abort();
105+
// oxlint-disable-next-line react/exhaustive-effect-dependencies -- A play request or Retry (attempt) reloads the source into the same player.
105106
}, [player, props.playRequested, attempt]);
106107

107108
return (

‎apps/mobile/src/components/VideoPreviewModal.tsx‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ function useLocalPlayback(source: LocalVideoPreviewSource): PlaybackState {
8787
() => undefined,
8888
);
8989
};
90+
// oxlint-disable-next-line react/exhaustive-effect-dependencies -- A different attachment restarts the load even when it resolves to the same cached file URI.
9091
}, [attachmentId, fileUri]);
9192
const mimeType = videoMimeType(attachment) ?? attachment.mimeType;
9293
return {
@@ -208,9 +209,10 @@ export function VideoPreviewModal(props: {
208209
}) {
209210
const isFocused = useIsFocused();
210211
const hasSource = props.source !== null;
212+
const { onRequestClose } = props;
211213
useEffect(() => {
212-
if (!isFocused && hasSource) props.onRequestClose();
213-
}, [isFocused, hasSource, props.onRequestClose]);
214+
if (!isFocused && hasSource) onRequestClose();
215+
}, [isFocused, hasSource, onRequestClose]);
214216
const { source } = props;
215217
if (source === null || !isFocused) return null;
216218
return source.type === "local" ? (

‎apps/mobile/src/features/diffs/nativeReviewDiffSurface.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ function useNativeReviewDiffPayload(
263263
cancelAnimationFrame(frame);
264264
}
265265
};
266+
// oxlint-disable-next-line react/exhaustive-effect-dependencies -- A new resetKey redelivers an unchanged payload after the diff surface resets.
266267
}, [method, nativeRef, payload, resetKey, onFailure, onDelivered]);
267268
}
268269

‎apps/mobile/src/features/files/SourceFileSurface.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ function JavaScriptSourceFileSurface(props: SourceFileSurfaceProps) {
254254
listRef.current?.scrollToIndex({ index: targetIndex, animated: false, viewPosition: 0.3 });
255255
});
256256
return () => cancelAnimationFrame(frame);
257+
// oxlint-disable-next-line react/exhaustive-effect-dependencies -- Opening another file at the same line index scrolls the new file to it.
257258
}, [props.path, targetIndex]);
258259

259260
const renderLine = ({ item, index }: { item: string; index: number }) => (

‎apps/mobile/src/features/home/HomeScreen.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ export function HomeScreen(props: HomeScreenProps) {
484484
bumpSnoozeWakeTick((tick) => tick + 1);
485485
}, delayMs);
486486
return () => clearTimeout(id);
487-
// snoozeWakeTick re-arms clamped timers even when the wake date exceeds 32-bit setTimeout and stays unchanged.
487+
// oxlint-disable-next-line react/exhaustive-effect-dependencies -- snoozeWakeTick re-arms clamped timers even when the wake date exceeds 32-bit setTimeout and stays unchanged.
488488
}, [nextSnoozeWakeAt, snoozeWakeTick]);
489489
// Called as `props.onSelectThread(...)`, the compiler would cache this handler on the whole
490490
// props object, which is new on every render of Home's parent.

‎apps/mobile/src/features/layout/AdaptiveWorkspaceLayout.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ export function useRegisterWorkspaceInspector(render: (() => ReactNode) | undefi
148148
if (focusedRef.current) {
149149
syncRegistration();
150150
}
151+
// oxlint-disable-next-line react/exhaustive-effect-dependencies -- Changed pane content replaces its existing native workspace registration.
151152
}, [wrappedRender]);
152153

153154
useEffect(

‎apps/mobile/src/features/pull-requests/PullRequestRouteScreen.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ export function PullRequestRouteScreen({ route }: StaticScreenProps<PullRequestP
389389
currentScrollOffset.current = scrollOffsets.current.overview ?? -insets.top;
390390
setSection("overview");
391391
}
392-
}, [guidesEnabled, section, insets.top]);
392+
}, [guidesEnabled, section, insets.top, currentScrollOffset, requestedSection, scrollOffsets]);
393393
const tabContent = activityContent;
394394
const filesY = useRef(0);
395395
const descriptionY = useRef(0);

‎apps/mobile/src/features/review/ReviewSheet.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,7 @@ export function ReviewSheet(props: ReviewSheetProps) {
453453

454454
useEffect(() => {
455455
showAuxiliaryPane("inspector");
456+
// oxlint-disable-next-line react/exhaustive-effect-dependencies -- Opening review for another thread reselects its inspector pane.
456457
}, [environmentId, showAuxiliaryPane, threadId]);
457458
const {
458459
error,

‎apps/mobile/src/features/threads/NewTaskDraftScreen.tsx‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,7 @@ export function NewTaskDraftScreen(props: {
513513
projects,
514514
flow.draftKey,
515515
props.initialProjectRef,
516+
// oxlint-disable-next-line react/exhaustive-effect-dependencies -- Opening a draft from a share, pending task, or draft id re-resolves its project.
516517
props.incomingShareId,
517518
props.pendingTaskId,
518519
props.draftId,
@@ -522,6 +523,7 @@ export function NewTaskDraftScreen(props: {
522523
setProject,
523524
]);
524525

526+
const { loadBranches } = flow;
525527
useEffect(() => {
526528
if (!selectedProject) {
527529
loadedBranchesProjectKeyRef.current = null;
@@ -532,8 +534,8 @@ export function NewTaskDraftScreen(props: {
532534
return;
533535
}
534536
loadedBranchesProjectKeyRef.current = projectKey;
535-
flow.loadBranches();
536-
}, [flow.loadBranches, selectedProject]);
537+
loadBranches();
538+
}, [loadBranches, selectedProject]);
537539

538540
useEffect(() => {
539541
const shareId = props.incomingShareId;
@@ -745,6 +747,7 @@ export function NewTaskDraftScreen(props: {
745747
consumeShare,
746748
cancelledIncomingShareId,
747749
flow.draftKey,
750+
// oxlint-disable-next-line react/exhaustive-effect-dependencies -- hasImportedIncomingShare reflects the draft store; a change re-checks whether the share still needs importing.
748751
hasImportedIncomingShare,
749752
incomingShare,
750753
isIncomingShareInboxLoading,

0 commit comments

Comments
 (0)