diff --git a/mobile/src/session/use-mobile-session-accessory-selection.ts b/mobile/src/session/use-mobile-session-accessory-selection.ts index 069212f4334..356bf11952d 100644 --- a/mobile/src/session/use-mobile-session-accessory-selection.ts +++ b/mobile/src/session/use-mobile-session-accessory-selection.ts @@ -46,6 +46,7 @@ export function useMobileSessionAccessorySelection(scope: MobileSessionTerminalI const repeatIntervalRef = useRef | null>(null) // Why: ref keeps repeat firing the current callback; else a mid-hold tab switch/reconnect routes bytes to a stale terminal. const handleAccessoryKeyRef = useRef(handleAccessoryKey) + // react-doctor-disable-next-line react-doctor/no-ref-current-in-render handleAccessoryKeyRef.current = handleAccessoryKey const stopAccessoryRepeat = useCallback(() => { if (repeatTimeoutRef.current) { diff --git a/mobile/src/session/use-mobile-session-feedback-capabilities.ts b/mobile/src/session/use-mobile-session-feedback-capabilities.ts index 66d2abf1bcd..8c619fb1f7f 100644 --- a/mobile/src/session/use-mobile-session-feedback-capabilities.ts +++ b/mobile/src/session/use-mobile-session-feedback-capabilities.ts @@ -35,6 +35,7 @@ export function useMobileSessionFeedbackCapabilities(scope: MobileSessionTermina // Why: stable callbacks (handleFileTap) read the live value via this ref, since // the capability probe resolves after the callbacks are created. const browserScreencastSupportedRef = useRef(browserScreencastSupported) + // react-doctor-disable-next-line react-doctor/no-ref-current-in-render browserScreencastSupportedRef.current = browserScreencastSupported // Why: terminal gesture/input callbacks are stable/imperative, so keep their refs current before commit, not in a later effect. clientRef.current = client @@ -49,6 +50,7 @@ export function useMobileSessionFeedbackCapabilities(scope: MobileSessionTermina ) // Why: Expo can reuse this screen for a new route; reconcile before paint so a dismissed old warning doesn't flash. if (reconciledCreateWarningState !== createWarningState) { + // react-doctor-disable-next-line react-doctor/no-prop-callback-in-render setCreateWarningState(reconciledCreateWarningState) } const createWarning = reconciledCreateWarningState.visible diff --git a/mobile/src/session/use-mobile-session-startup.ts b/mobile/src/session/use-mobile-session-startup.ts index 3eca98ae13f..f33d081f2cc 100644 --- a/mobile/src/session/use-mobile-session-startup.ts +++ b/mobile/src/session/use-mobile-session-startup.ts @@ -95,6 +95,8 @@ export function useMobileSessionStartup(scope: MobileSessionKeyboardStateModel) worktreeId ]) + // Every setTimeout goes through addTimer into `timers`, which the returned cleanup clears. + // react-doctor-disable-next-line react-doctor/effect-needs-cleanup useEffect(() => { if (connState !== 'connected') { return diff --git a/mobile/src/session/use-mobile-session-terminal-runtime.ts b/mobile/src/session/use-mobile-session-terminal-runtime.ts index ab909254e10..8ef472fb845 100644 --- a/mobile/src/session/use-mobile-session-terminal-runtime.ts +++ b/mobile/src/session/use-mobile-session-terminal-runtime.ts @@ -76,7 +76,6 @@ export function useMobileSessionTerminalRuntime(scope: MobileSessionScreenStateM const activeHandleRef = useRef(null) const bufferedTerminalDraftState = useBufferedTerminalDrafts({ activeHandle, activeHandleRef }) const reconcileBufferedDraftsRef = useRef(bufferedTerminalDraftState.reconcileTerminalTabs) - reconcileBufferedDraftsRef.current = bufferedTerminalDraftState.reconcileTerminalTabs const activeSessionTabTypeRef = useRef(null) const pendingActiveSessionTabIdRef = useRef(null) const pendingActiveTerminalHandleRef = useRef(null) diff --git a/mobile/src/session/use-mobile-session-terminal-subscription-foundation.ts b/mobile/src/session/use-mobile-session-terminal-subscription-foundation.ts index 0289a1c65e9..76d8229b288 100644 --- a/mobile/src/session/use-mobile-session-terminal-subscription-foundation.ts +++ b/mobile/src/session/use-mobile-session-terminal-subscription-foundation.ts @@ -61,6 +61,8 @@ export function useMobileSessionTerminalSubscriptionFoundation( [clearNativeChatInputLease, nativeChatInputLeaseReadyRef, showNativeChatRef] ) const unsubscribeTerminalRef = useRef(unsubscribeTerminal) + // PTY event callbacks fire before passive effects flush, so they need the current unsubscribe. + // react-doctor-disable-next-line react-doctor/no-ref-current-in-render unsubscribeTerminalRef.current = unsubscribeTerminal const clearTerminalCache = useCallback(() => {