AnimatePresent not unmounts component when using 'worklet'
Closed this issue · 14 comments
Is there an existing issue for this?
- I have searched the existing issues
Current Behavior
Component remains in tree and not umounted after exit.
Expected Behavior
Component should be unmounted after exit
Steps To Reproduce
- Use
exit
prop with worklet
Versions
- Moti: 0.18.0
- Reanimated: 2.8.0
- React Native: 0.68.2
- Expo: 45.0.4
Screenshots
No response
Reproduction
function MyComponent() {
const forward = true
return (
<AnimatePresence custom={forward} initial={false}>
<MotiView
key={index}
style={[StyleSheet.absoluteFill, styles.content]}
from={forward ? ANIMATE_RT : ANIMATE_LT_STACK}
animate={{ translateX: 0 }}
// exit={{ opacity: 0 }} // <- with this component unmounts
exit={(custom) => {
'worklet'
// With 'worklet' exit components still exist in tree and proceed weird animations
return custom ? ANIMATE_LT_STACK : ANIMATE_RT
}}
transition={TRANSITION}
>
{arr[index]}
</MotiView>
</AnimatePresence>
)
}
const ANIMATE_RT = {
translateX: WIDTH,
zIndex: 10,
}
const ANIMATE_LT_STACK = { translateX: -WIDTH, zIndex: 5 }
const ANIMATE_LT = { translateX: -WIDTH }
const TRANSITION: TransitionConfig = {
type: 'timing',
duration: 2000,
easing: Easing.out(Easing.cubic),
}
const styles = StyleSheet.create({
content: {
overflow: 'hidden',
},
})
what happens if you define these objects inside of the worklet?
Just now tried like this:
exit={(custom) => {
'worklet'
return custom
? { translateX: -WIDTH, zIndex: 5 }
: {
translateX: WIDTH,
zIndex: 10,
}
}}
Still the same issue
can you take out zIndex and apply that directly to style? that can’t be animated
Thanks a lot! Without zIndex everything works.
Maybe, it can be useful to add some warning in development when using wrong props.
yeah there is a list of invalid props for exits, would be great if you could send a PR to add zIndex. otherwise i’ll do it next time i have time
Hm.. With opacity i have the same problem when component not unmounts:
exit={(custom) => {
'worklet'
return custom
? { translateX: -WIDTH }
: {
translateX: WIDTH,
opacity: 0, // <- remove opacity and component will unmount
}
}}
make sure that you set the value it should animate from in other places. unlike framer motion, moti does not set default values. so you need to set opacity to 1 in animate
or from
if you want it to transition out to 0
I tried:
<MotiView
key={index}
style={[StyleSheet.absoluteFill, styles.content, { zIndex: index }]}
from={forward ? ANIMATE_RT : ANIMATE_LT_STACK}
animate={ANIMATE_IN}
exit={(custom) => {
'worklet'
return custom ? ANIMATE_LT_STACK : ANIMATE_RT
}}
transition={TRANSITION}
>
{arr[index]}
</MotiView>
const ANIMATE_RT = { translateX: WIDTH, opacity: 1 }
const ANIMATE_LT_STACK = { translateX: -WIDTH / 4, opacity: 0.5 } // <- remove opacity from here and it will work
const ANIMATE_LT = { translateX: -WIDTH, opacity: 1 }
const ANIMATE_IN = { translateX: 0, opacity: 1 }
weird. what’s the transition
oddly I can't reproduce this. could you try making an expo snack maybe?
I'm having the same issue and I tried making an expo snack with the same code and moti version (0.18) and somehow it works fine on the snack (https://snack.expo.dev/9X0_pM9sS) but not in a dev environment
chances are, there's some other reason. is it an expensive component? AnimatePresence should only be used for simple animations usually, not for deeply-nested components