11import React , { ReactNode , useEffect , useRef } from 'react' ;
2- import { LayoutChangeEvent , Platform , View } from 'react-native' ;
2+ import { Platform , View } from 'react-native' ;
33
4+ import Animated , { useAnimatedStyle , useSharedValue } from 'react-native-reanimated' ;
45import { useSafeAreaInsets } from 'react-native-safe-area-context' ;
56import { Portal } from 'react-native-teleport' ;
67
@@ -66,43 +67,38 @@ export const PortalWhileClosingView = ({
6667} : PortalWhileClosingViewProps ) => {
6768 const { closing } = useOverlayController ( ) ;
6869 const containerRef = useRef < View | null > ( null ) ;
69- const absolutePositionRef = useRef < { x : number ; y : number } | null > ( null ) ;
70- const layoutRef = useRef < { h : number ; w : number } > ( { h : 0 , w : 0 } ) ;
70+ const placeholderLayout = useSharedValue ( { h : 0 , w : 0 } ) ;
7171 const insets = useSafeAreaInsets ( ) ;
7272
73- useEffect ( ( ) => {
74- let cancelled = false ;
75-
76- const measureAbsolutePosition = ( ) => {
77- containerRef . current ?. measureInWindow ( ( x , y ) => {
78- if ( cancelled ) return ;
79- const absolute = {
80- x,
81- y : y + ( Platform . OS === 'android' ? insets . top : 0 ) ,
82- } ;
73+ const syncPortalLayout = useStableCallback ( ( ) => {
74+ containerRef . current ?. measureInWindow ( ( x , y , width , height ) => {
75+ const absolute = {
76+ x,
77+ y : y + ( Platform . OS === 'android' ? insets . top : 0 ) ,
78+ } ;
8379
84- absolutePositionRef . current = absolute ;
80+ if ( ! width || ! height ) {
81+ return ;
82+ }
8583
86- const { h, w } = layoutRef . current ;
87- if ( ! w || ! h ) return ;
84+ placeholderLayout . value = { h : height , w : width } ;
8885
89- setClosingPortalLayout ( portalHostName , {
90- ...absolute ,
91- h,
92- w,
93- } ) ;
86+ setClosingPortalLayout ( portalHostName , {
87+ ...absolute ,
88+ h : height ,
89+ w : width ,
9490 } ) ;
95- } ;
91+ } ) ;
92+ } ) ;
9693
94+ useEffect ( ( ) => {
9795 // Measure once after mount and layout settle.
9896 requestAnimationFrame ( ( ) => {
99- requestAnimationFrame ( measureAbsolutePosition ) ;
97+ requestAnimationFrame ( ( ) => {
98+ syncPortalLayout ( ) ;
99+ } ) ;
100100 } ) ;
101-
102- return ( ) => {
103- cancelled = true ;
104- } ;
105- } , [ insets . top , portalHostName ] ) ;
101+ } , [ insets . top , portalHostName , syncPortalLayout ] ) ;
106102
107103 const unregisterPortalHost = useStableCallback ( ( ) => clearClosingPortalLayout ( portalHostName ) ) ;
108104
@@ -112,29 +108,19 @@ export const PortalWhileClosingView = ({
112108 } ;
113109 } , [ unregisterPortalHost ] ) ;
114110
115- const onWrapperViewLayout = useStableCallback ( ( event : LayoutChangeEvent ) => {
116- const { height, width } = event . nativeEvent . layout ;
117- layoutRef . current = { h : height , w : width } ;
118-
119- const absolute = absolutePositionRef . current ;
120- if ( ! absolute ) return ;
121-
122- setClosingPortalLayout ( portalHostName , { ...absolute , h : height , w : width } ) ;
123- } ) ;
111+ const placeholderStyle = useAnimatedStyle ( ( ) => ( {
112+ height : placeholderLayout . value . h ,
113+ width : placeholderLayout . value . w > 0 ? placeholderLayout . value . w : '100%' ,
114+ } ) ) ;
124115
125116 return (
126117 < >
127118 < Portal hostName = { closing ? portalHostName : undefined } name = { portalName } >
128- < View collapsable = { false } ref = { containerRef } onLayout = { onWrapperViewLayout } >
119+ < View collapsable = { false } ref = { containerRef } onLayout = { syncPortalLayout } >
129120 { children }
130121 </ View >
131122 </ Portal >
132- { closing && layoutRef . current . h > 0 ? (
133- < View
134- pointerEvents = 'none'
135- style = { { height : layoutRef . current . h , width : layoutRef . current . w || '100%' } }
136- />
137- ) : null }
123+ { closing ? < Animated . View pointerEvents = 'none' style = { placeholderStyle } /> : null }
138124 </ >
139125 ) ;
140126} ;
0 commit comments