From 7f4dbe9454d4ebc2e836777c9b28fe04943d18f3 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 9 Feb 2024 19:56:35 +0000 Subject: [PATCH] Measure header layout reliably (#2817) * Measure header layout reliably * grammar --- src/view/com/pager/PagerWithHeader.tsx | 37 +++++++++++++++----------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/view/com/pager/PagerWithHeader.tsx b/src/view/com/pager/PagerWithHeader.tsx index dcfc616c..938c1e7e 100644 --- a/src/view/com/pager/PagerWithHeader.tsx +++ b/src/view/com/pager/PagerWithHeader.tsx @@ -233,35 +233,40 @@ let PagerTabBar = ({ }, ], })) - const headerRef = React.useRef(null) - React.useEffect(() => { - // Fire when layout *becomes* ready. - // We can't rely on onLayout alone because it won't fire if layout is the same. - // We can't rely on this effect alone because it won't fire if layout changes later. - if (isHeaderReady) { - // @ts-ignore - headerRef.current!.measure( - (_x: number, _y: number, _width: number, height: number) => { - onHeaderOnlyLayout(height) - }, - ) - } - }, [isHeaderReady, onHeaderOnlyLayout]) - + const pendingHeaderHeight = React.useRef(null) return ( { if (isHeaderReady) { onHeaderOnlyLayout(e.nativeEvent.layout.height) + pendingHeaderHeight.current = null + } else { + // Stash it away for when `isHeaderReady` turns `true` later. + pendingHeaderHeight.current = e.nativeEvent.layout.height } }}> {renderHeader?.()} + { + // When `isHeaderReady` turns `true`, we want to send the parent layout. + // However, if that didn't lead to a layout change, parent `onLayout` wouldn't get called again. + // We're conditionally rendering an empty view so that we can send the last measurement. + isHeaderReady && ( + { + // We're assuming the parent `onLayout` already ran (parent -> child ordering). + if (pendingHeaderHeight.current !== null) { + onHeaderOnlyLayout(pendingHeaderHeight.current) + pendingHeaderHeight.current = null + } + }} + /> + ) + }