An ATproto social media client -- with an independent Appview.

Measure header layout reliably (#2817)

* Measure header layout reliably

* grammar

authored by danabra.mov and committed by

GitHub 7f4dbe94 071efaf2

+21 -16
+21 -16
src/view/com/pager/PagerWithHeader.tsx
··· 233 233 }, 234 234 ], 235 235 })) 236 - const headerRef = React.useRef(null) 237 - React.useEffect(() => { 238 - // Fire when layout *becomes* ready. 239 - // We can't rely on onLayout alone because it won't fire if layout is the same. 240 - // We can't rely on this effect alone because it won't fire if layout changes later. 241 - if (isHeaderReady) { 242 - // @ts-ignore 243 - headerRef.current!.measure( 244 - (_x: number, _y: number, _width: number, height: number) => { 245 - onHeaderOnlyLayout(height) 246 - }, 247 - ) 248 - } 249 - }, [isHeaderReady, onHeaderOnlyLayout]) 250 - 236 + const pendingHeaderHeight = React.useRef<null | number>(null) 251 237 return ( 252 238 <Animated.View 253 239 pointerEvents="box-none" 254 240 style={[styles.tabBarMobile, headerTransform]}> 255 241 <View 256 - ref={headerRef} 257 242 pointerEvents="box-none" 258 243 collapsable={false} 259 244 onLayout={e => { 260 245 if (isHeaderReady) { 261 246 onHeaderOnlyLayout(e.nativeEvent.layout.height) 247 + pendingHeaderHeight.current = null 248 + } else { 249 + // Stash it away for when `isHeaderReady` turns `true` later. 250 + pendingHeaderHeight.current = e.nativeEvent.layout.height 262 251 } 263 252 }}> 264 253 {renderHeader?.()} 254 + { 255 + // When `isHeaderReady` turns `true`, we want to send the parent layout. 256 + // However, if that didn't lead to a layout change, parent `onLayout` wouldn't get called again. 257 + // We're conditionally rendering an empty view so that we can send the last measurement. 258 + isHeaderReady && ( 259 + <View 260 + onLayout={() => { 261 + // We're assuming the parent `onLayout` already ran (parent -> child ordering). 262 + if (pendingHeaderHeight.current !== null) { 263 + onHeaderOnlyLayout(pendingHeaderHeight.current) 264 + pendingHeaderHeight.current = null 265 + } 266 + }} 267 + /> 268 + ) 269 + } 265 270 </View> 266 271 <View 267 272 onLayout={onTabBarLayout}