You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am having a very weird issue that I am not able to troubleshoot after spending a few hours on it.
Summary
I am animating a modal using Reanimated, and sometimes the modal never appears with an animation, but only on the next touch on the device screen / when browsing layout in Flipper.
If I add a console.log call in useAnimatedStyle, then it works flawlessly…
Implementation
Reanimated is used to display a modal panel, using a wrapper around the modal content.
The wrapper keeps its own state (closed, opening, opened, closing) and animates:
translateY when opening/closing the modal
height when the modal content changes.
It exposes (through a context) 2 shared values, used by the modal content components to expose:
totalContentHeight: the total height of the content to display (inner content of a ScrollView)
contentHeight: the actuel height of the inner ScrollView, computed so it fits the screen
It then uses these values to transition between states, and set an animated view around the component with the needed style.
The initial transition (closed => opening is triggered using useEffect, and the translation animation (appear) does not start until a contentHeight is computed (meaning totalContentHeight has been set by the modal content component).
Click to see sample code (simplified)
constModalWrapper: React.FC<{children: React.ReactNode}>=({
children,})=>{// this is the modal scrollview content (total content height)consttotalContentHeight=useSharedValue(0);// the scrollview height (less than the total content if it does not fit the screen)constcontentHeight=useSharedValue(0);// padding at the bottom of the modalconstbottomPadding=useSharedValue(0);constopenState=useSharedValue<"closed"|"opening"|"opened"|"closing">("closed");const{height: screenHeight}=useWindowDimensions();// When the component is mounted, let's update the modaluseEffect(()=>{openState.value="opening";},[openState]);// When the modal needs to be closed, we dont really close it but launch the animation// The real close will be called at the end of the animationconsthideModal=useCallback(()=>{openState.value="closing";},[openState]);// react to the various value changesuseAnimatedReaction(()=>{constpadding=20;constmaxContentSize=screenHeight-200-padding;// compute the maximum displayed height for modal contentreturn[Math.round(Math.min(totalContentHeight.value,maxContentSize)),padding,]asconst;},([height,padding])=>{contentHeight.value=height;bottomPadding.value=padding;},[screenHeight]);constmodalAnimatedStyle=useAnimatedStyle(()=>{letheight=contentHeight.value;lettranslateY=-height||10000;// initially we render the modal way below the fold, so its invisible until displayed and content height calculatedswitch(openState.value){case"closed":
// do nothingbreak;case"opening":
if(height>0){translateY=withSequence(// first move it just below the bottom of the screenwithTiming(height,{duration: 0}),// then do the opening animationwithTiming(0,{duration: APPEAR_DURATION},()=>{openState.value="opened";}));// If we remove this log, then sometimes the modal does not displays// But it always displays when we log?// console.log("Modal opened. Do not remove this log.");}// otherwise we let it be hiddenbreak;case"closing":
translateY=withTiming(height,{duration: APPEAR_DURATION},()=>{openState.value="closed";});break;case"opened":
// animate height when content changesheight=withTiming(height,{duration: APPEAR_DURATION});break;}return{
height,transform: [{ translateY }],};});return(<Animated.Viewstyle={[styles.modalContainer,modalAnimatedStyle]}><modalInnerContext.Providervalue={useMemo(()=>({actions: {
showModal,
hideModal,},
totalContentHeight,
contentHeight,
bottomPadding,}),[hideModal,showModal,totalContentHeight,contentHeight,bottomPadding,])}>{children}</modalInnerContext.Provider></Animated.View>);};
Issue detail
These tests are done using an iPhone simulator
When opening/closing repeatedly the modal, at some point opening does nothing. The useEffect is triggered, but nothing else happen on the screen.
I can get the modal to appear (instantly, without animation), if:
If I touch the screen (anywhere)
If I browse the layout in Flipper without any input in the simulator, after some time (did not find out exactly when)
The very weird thing is that if I uncomment the console.log call in my useAnimatedStyle, then it works flawlessly all the time. I tried to call a dummy function using runOnJS but it does not work, this seems to need to be a console.log call.
I tried to upgrade to Reanimated 3 RC0, the behaviour is the same.
Does somebody have an idea on:
what could be causing this?
how can I troubleshoot this further? As it only happens when I dont use console.log, it makes it very hard to pinpoint…
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Hi there,
I am having a very weird issue that I am not able to troubleshoot after spending a few hours on it.
Summary
I am animating a modal using Reanimated, and sometimes the modal never appears with an animation, but only on the next touch on the device screen / when browsing layout in Flipper.
If I add a
console.log
call inuseAnimatedStyle
, then it works flawlessly…Implementation
Reanimated is used to display a modal panel, using a wrapper around the modal content.
The wrapper keeps its own state (closed, opening, opened, closing) and animates:
translateY
when opening/closing the modalheight
when the modal content changes.It exposes (through a context) 2 shared values, used by the modal content components to expose:
totalContentHeight
: the total height of the content to display (inner content of aScrollView
)contentHeight
: the actuel height of the innerScrollView
, computed so it fits the screenIt then uses these values to transition between states, and set an animated view around the component with the needed style.
The initial transition (
closed
=>opening
is triggered usinguseEffect
, and the translation animation (appear) does not start until acontentHeight
is computed (meaningtotalContentHeight
has been set by the modal content component).Click to see sample code (simplified)
Issue detail
These tests are done using an iPhone simulator
When opening/closing repeatedly the modal, at some point opening does nothing. The
useEffect
is triggered, but nothing else happen on the screen.I can get the modal to appear (instantly, without animation), if:
The very weird thing is that if I uncomment the
console.log
call in myuseAnimatedStyle
, then it works flawlessly all the time. I tried to call a dummy function usingrunOnJS
but it does not work, this seems to need to be aconsole.log
call.I tried to upgrade to Reanimated 3 RC0, the behaviour is the same.
Does somebody have an idea on:
console.log
, it makes it very hard to pinpoint…Beta Was this translation helpful? Give feedback.
All reactions