nandorojo/moti

AnimatePresence + Hermes doesn't work

davidnum opened this issue Β· 28 comments

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

MotiView stuck/freeze appearing animation when wrapped in AnimatedPresence with exitBeforeEnter prop. Patch from #195 and changes in #200 does not fix this bug.

Bug not exists in moti@0.17.1

Steps To Reproduce

  1. Only happens when MotiView has multiple animated properties:
 <MotiView
    from={{ opacity: 0,   scale: 0.9 }}
    animate={{ opacity: 1, scale: 1 }}
    exit={{ opacity: 0, scale: 0.9 }}
  />
  1. Wrap MotiView into AnimatePresence with exitBeforeEnter prop
  2. Enable hermes in Podfile

Versions

- Moti: 0.18.0
- Reanimated: 2.9.1
- React Native: 0.67.4 - 0.69

Screenshots

Current Behavior:

2022-07-26.02.44.09.mov

Expected Behavior:

2022-07-26.02.48.49.mov

Reproduction

https://github.com/davidnum/motibug

Interesting, so this works without Hermes for you? What version of Hermes?

And you're saying that this only happens with Moti 0.18, but not 0.17?

Interesting, so this works without Hermes for you? What version of Hermes?

Expected behavior video recorded without enabling hermes.
Hermes versions: 0.10, 0.11.

And you're saying that this only happens with Moti 0.18, but not 0.17?

Yeah, on 0.17.1 it works as expected.

I see. It looks like this would be caused by the Framer Motion upgrade in moti@0.18.0:

Could you try adding this to your package.json?

{
  "resolutions": { "framer-motion": "3.9.1" }
}

And then run yarn install --force

I see. It looks like this would be caused by the Framer Motion upgrade in moti@0.18.0:

Could you try adding this to your package.json?

{
  "resolutions": { "framer-motion": "3.9.1" }
}

And then run yarn install --force

Didn't help :(

🧐

i can’t see anything else in the change log that would be unique to 0.18 causing problems…what’s the full code?

🧐

i can’t see anything else in the change log that would be unique to 0.18 causing problems…what’s the full code?

https://github.com/davidnum/motibug

Having the same issue on Android (not iOS) on moti 0.18

@faz919 and disabling hermes solves it?

Not sure but downgrading to moti 0.17.1 fixed the issue.

did you try the yarn resolution?

nah. Was in a time crunch and had to do fastest possible solution

@nandorojo hi, any news?

@nandorojo Resolution doesn't seem to be working.

{
"resolutions": { "framer-motion": "3.9.1" }
}

Another issue that I have is that onExitComplete never seems to fire on 0.18.0 whenever I provide two types of animations {opacity: 0, translateY: 50} , however it does work with one value {opacity: 0}.

Seems to work properly on lower versions. So for now I'm downgrading to 0.17.1 until there is a fix.

Edit:

In 0.17.1 MotiPressable onPress event seems to be broken, <Pressable /> from react-native works, not sure what's going on there.

Just noticed #143 #179.

Thanks for the update. I'll keep looking into it soon when I have some time. I'm convinced it's a dependency-related issue.

Jemaz commented

Also to add, using sequences with the useDynamicAnimation hook is broken with Hermes enabled.

For example, the below will not work with the latest Expo (SDK 46) and Hermes enabled (was working before when Hermes was disabled):

import { Pressable } from "native-base";
import { useDynamicAnimation } from "moti";
const animation = useDynamicAnimation(() => {
    return {
      scale: 1
    }
  })
<Pressable onPress={() => {
  animation.animateTo({
    scale: [1.2, { value: 1, type: 'spring' }]
  })
}}>
  <MotiView state={animation}>
    <Text>Placeholder...</Text>
  </MotiView>
</Pressable>

I think you are right @nandorojo this being a dependency-related and it might not be scoped to just using AnimatePresence.

Oof Hermes is killing me here! Haha

Jemaz commented

I feel very sorry for you now, haha 🀣

Just a heads up, I've updated the code with the one that actually throws the error, and throws this:
image

Also, for those strolling here and was stuck like me, what I wanted to achieve it to animate the sequence, I think Hermes with different JS support language features doesn't allow the previous syntax or it could be a react-reanimated issue. Anyways I fixed my issue by tweaking the syntax like this:

import { Pressable } from "native-base";
import { useDynamicAnimation } from "moti";
const animation = useDynamicAnimation(() => {
    return {
      scale: 1
    }
  })
<Pressable onPress={() => {
 animation.animateTo({
              scale: [
                { value: 1.2, type: 'spring', duration: 500 },
                { value: 1, type: 'spring' }
              ]
            })
}}>
  <MotiView state={animation}>
    <Text>Placeholder...</Text>
  </MotiView>
</Pressable>

Having the same issue here, unfortunately 😒 .. and for me, trying to downgrade to 0.17.1, is not a possible workaround, because I'm already using the React 18 and with that the children is missing

I'm experiencing the same issue as well and not using hermes, downgrading to 0.17.1 seems to work for me. I'm using:

  • expo 47.0.3
  • Moti 0.21.0
  • React Native 0.70.5
  • React reanimated 2.13.0

With Moti 0.21.0 this does not work:

<AnimatePresence exitBeforeEnter>
  <MotiView
    key={item.id}
    from={{
      opacity: 0,
      transform: [{ translateY: -10 }],
    }}
    animate={{
      opacity: 1,
      transform: [{ translateY: 0 }],
    }}
    exit={{
      opacity: 0,
      transform: [{ translateY: -10 }],
    }}
    transition={{ type: "timing", duration: 400, delay: 50 }}
    >
    <Text>{item.title}</Text>
  </MotiView>
</AnimatePresence>

item is set via a prop in another component. Code above does work on Moti 0.17.1

could you do me a favor and runyarn why framer-motion before & after changing moti versions? i’m very curious if framer versions is the cause. I don’t see what else it could be.

Before:

=> Found "framer-motion@3.10.6"
info Reasons this module exists
   - "moti#@motify#core" depends on it
   - Hoisted from "moti#@motify#core#framer-motion"
info Disk size without dependencies: "4.82MB"
info Disk size with unique dependencies: "6.58MB"
info Disk size with transitive dependencies: "6.58MB"
info Number of shared dependencies: 5

After:

=> Found "framer-motion@6.5.1"
info Reasons this module exists
   - "moti" depends on it
   - Hoisted from "moti#framer-motion"
info Disk size without dependencies: "2.7MB"
info Disk size with unique dependencies: "5.5MB"
info Disk size with transitive dependencies: "6.57MB"
info Number of shared dependencies: 6

Okay so this must be it. Does the newest version work if you add a yarn resolution to framer 3.10.6?

I've added a resolution to my package.json for framer-motion:

"resolutions": {
    "framer-motion": "3.10.6"
  }

Then installed the latest Moti and ran yarn why framer-motion which results in version 3.10.6. Build and ran my app again but the problem still exists.

Reverted back to 0.17.1, build and ran my app and then it works as intended. When using 0.17.1 I do see that <AnimatePresence> is underlined in my IDE and when hovered refers to import { Frame, AnimatePresence } from 'framer' but is imported like so: import { AnimatePresence, MotiView } from "moti".

Hm, okay. Still a bit peculiar to me. Will try to figure it out when I can.

Alright, I'm deeply investigating. I've spent hours diffing lock files. Here are some findings.

  • ^0.17.1 works
  • ^0.18 does not work

Here is what it looks like to install it:

info Direct dependencies
└─ moti@0.18.0
info All dependencies
β”œβ”€ @motify/components@0.18.0
β”œβ”€ @motionone/animation@10.15.1
β”œβ”€ @motionone/dom@10.12.0
β”œβ”€ @motionone/easing@10.15.1
β”œβ”€ @motionone/generators@10.15.1
β”œβ”€ framer-motion@6.5.1
β”œβ”€ moti@0.18.0
└─ popmotion@11.0.3

I ran a diff of all files from moti and went one-by-one to see what the cause could be (yes really).

By pulling useMotify from 0.17 β†’ 0.18, I found that it started working again. This meant that something in the 0.18 change in the worklets made a difference. In that update, I improved performance by changing .forEach loops to use for (const key of) loops. I'm wondering if Hermes didn't like that...

I tried changing for (const key in mergedStyles) to Object.keys(mergedStyles).forEach(key => and...that did it 🧐.

So, I guess I have to refactor that back. This whole coding thing may not be for me lol

Moti finally works with Hermes in version 0.22. Please upgrade and let me know if it works for you. Appreciate your patience.