about summary refs log tree commit diff
path: root/src/view/com/pager/PagerWithHeader.tsx
diff options
context:
space:
mode:
authordan <dan.abramov@gmail.com>2024-02-14 04:12:30 +0000
committerGitHub <noreply@github.com>2024-02-14 04:12:30 +0000
commitb9301befb701e3562de81294048163c62349bcbe (patch)
tree46fbc0196f00ebc53b1ec9ae0210a8d18ca80957 /src/view/com/pager/PagerWithHeader.tsx
parent7e6b666ee36c996e9c3aa35fb5161e5d04e8b395 (diff)
downloadvoidsky-b9301befb701e3562de81294048163c62349bcbe.tar.zst
Fix layout measurements (again) (#2866)
Diffstat (limited to 'src/view/com/pager/PagerWithHeader.tsx')
-rw-r--r--src/view/com/pager/PagerWithHeader.tsx35
1 files changed, 14 insertions, 21 deletions
diff --git a/src/view/com/pager/PagerWithHeader.tsx b/src/view/com/pager/PagerWithHeader.tsx
index 938c1e7e8..aa110682a 100644
--- a/src/view/com/pager/PagerWithHeader.tsx
+++ b/src/view/com/pager/PagerWithHeader.tsx
@@ -233,36 +233,29 @@ let PagerTabBar = ({
       },
     ],
   }))
-  const pendingHeaderHeight = React.useRef<null | number>(null)
+  const headerRef = React.useRef(null)
   return (
     <Animated.View
       pointerEvents="box-none"
       style={[styles.tabBarMobile, headerTransform]}>
-      <View
-        pointerEvents="box-none"
-        collapsable={false}
-        onLayout={e => {
-          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
-          }
-        }}>
+      <View ref={headerRef} pointerEvents="box-none" collapsable={false}>
         {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.
+          // It wouldn't be enough to place `onLayout` on the parent node because
+          // this would risk measuring before `isHeaderReady` has turned `true`.
+          // Instead, we'll render a brand node conditionally and get fresh layout.
           isHeaderReady && (
             <View
+              // It wouldn't be enough to do this in a `ref` of an effect because,
+              // even if `isHeaderReady` might have turned `true`, the associated
+              // layout might not have been performed yet on the native side.
               onLayout={() => {
-                // We're assuming the parent `onLayout` already ran (parent -> child ordering).
-                if (pendingHeaderHeight.current !== null) {
-                  onHeaderOnlyLayout(pendingHeaderHeight.current)
-                  pendingHeaderHeight.current = null
-                }
+                // @ts-ignore
+                headerRef.current?.measure(
+                  (_x: number, _y: number, _width: number, height: number) => {
+                    onHeaderOnlyLayout(height)
+                  },
+                )
               }}
             />
           )