From 382710f93eb2b6a3a07afc384730a9b1b9e82b29 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 28 Feb 2026 21:05:20 +0000 Subject: [PATCH] Fix sourceViewTag resolution timing for sheet transitions findNodeHandle(ref.current) at render time returns undefined on the first render since the ref isn't populated yet. Fix this by: - Menu.Outer: use useEffect to resolve the tag after mount when the trigger ref is already populated - LabelsBtn/ThreadgateBtn: use callback refs to capture the node handle in state immediately when the button mounts https://claude.ai/code/session_011cNDhEb2cDgg5QbVuzEyH1 --- src/components/Menu/index.tsx | 21 +++++++++++++++---- src/view/com/composer/labels/LabelsBtn.tsx | 13 +++++++++--- .../com/composer/threadgate/ThreadgateBtn.tsx | 12 ++++++++--- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/components/Menu/index.tsx b/src/components/Menu/index.tsx index d1f2fb969c..3f1e641baf 100644 --- a/src/components/Menu/index.tsx +++ b/src/components/Menu/index.tsx @@ -1,4 +1,12 @@ -import {cloneElement, Fragment, isValidElement, useMemo, useRef} from 'react' +import { + cloneElement, + Fragment, + isValidElement, + useEffect, + useMemo, + useRef, + useState, +} from 'react' import { findNodeHandle, Pressable, @@ -106,9 +114,14 @@ export function Outer({ }>) { const context = useMenuContext() const {_} = useLingui() - const sourceViewTag = enableTransition - ? (findNodeHandle(context.triggerRef.current) ?? undefined) - : undefined + const [sourceViewTag, setSourceViewTag] = useState() + + useEffect(() => { + if (enableTransition && context.triggerRef.current) { + const tag = findNodeHandle(context.triggerRef.current) + if (tag != null) setSourceViewTag(tag) + } + }, [enableTransition, context.triggerRef]) return ( (null) + const [sourceViewTag, setSourceViewTag] = useState() + + const btnRef = (node: View | null) => { + if (node) { + const tag = findNodeHandle(node) + if (tag != null) setSourceViewTag(tag) + } + } const hasLabel = labels.length > 0 @@ -80,7 +87,7 @@ export function LabelsBtn({ control={control} nativeOptions={{ preventExpansion: true, - sourceViewTag: findNodeHandle(btnRef.current) ?? undefined, + sourceViewTag, }}> (null) + const [sourceViewTag, setSourceViewTag] = useState() + const btnRef = (node: View | null) => { + if (node) { + const tag = findNodeHandle(node) + if (tag != null) setSourceViewTag(tag) + } + } const [threadgateNudged, setThreadgateNudged] = useThreadgateNudged() const [showTooltip, setShowTooltip] = useState(false) const [tooltipWasShown] = useState(!threadgateNudged) @@ -175,7 +181,7 @@ export function ThreadgateBtn({ { if (persist) { persistChanges({