From 68ad291d3deadf7175ec97808cefac3114e31ed2 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Sat, 30 May 2026 19:26:00 -0700 Subject: [PATCH] Resolve bottom drawer mount before commit (#3226) Co-authored-by: Jinwoo-H --- mobile/src/components/BottomDrawer.tsx | 14 ++++++++------ .../components/bottom-drawer-mount-state.test.ts | 11 +++++++++++ mobile/src/components/bottom-drawer-mount-state.ts | 3 +++ 3 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 mobile/src/components/bottom-drawer-mount-state.test.ts create mode 100644 mobile/src/components/bottom-drawer-mount-state.ts diff --git a/mobile/src/components/BottomDrawer.tsx b/mobile/src/components/BottomDrawer.tsx index e96f035c2..a0d154c42 100644 --- a/mobile/src/components/BottomDrawer.tsx +++ b/mobile/src/components/BottomDrawer.tsx @@ -22,6 +22,7 @@ import Animated, { Extrapolation } from 'react-native-reanimated' import { colors, spacing } from '../theme/mobile-theme' +import { resolveBottomDrawerMounted } from './bottom-drawer-mount-state' import { useResponsiveLayout } from '../layout/responsive-layout' const DISMISS_THRESHOLD = 80 @@ -50,16 +51,17 @@ export function BottomDrawer({ zIndex }: Props) { const [mounted, setMounted] = useState(visible) + const resolvedMounted = resolveBottomDrawerMounted(visible, mounted) - useEffect(() => { - if (visible) { - setMounted(true) - } - }, [visible]) + // Why: opening drawers should mount before commit; waiting for a passive + // Effect adds a null render before every drawer can animate in. + if (resolvedMounted !== mounted) { + setMounted(resolvedMounted) + } // Why: hidden drawers are rendered by parent screens even while closed; keep // their Reanimated/Gesture setup out of hot paths like commit-message typing. - if (!mounted) return null + if (!resolvedMounted) return null return ( { + it('mounts before opening and stays mounted while closing', () => { + expect(resolveBottomDrawerMounted(true, false)).toBe(true) + expect(resolveBottomDrawerMounted(true, true)).toBe(true) + expect(resolveBottomDrawerMounted(false, true)).toBe(true) + expect(resolveBottomDrawerMounted(false, false)).toBe(false) + }) +}) diff --git a/mobile/src/components/bottom-drawer-mount-state.ts b/mobile/src/components/bottom-drawer-mount-state.ts new file mode 100644 index 000000000..3e9a7f110 --- /dev/null +++ b/mobile/src/components/bottom-drawer-mount-state.ts @@ -0,0 +1,3 @@ +export function resolveBottomDrawerMounted(visible: boolean, mounted: boolean): boolean { + return visible || mounted +}