question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Sequence not working since reanimated 2.3.0

See original GitHub issue

Since reanimated 2.3.0 I was no longer able to use Moti sequence animations

I’m getting the error:

Exception in HostFunction: Javascript worklet error

For any sequence animation

  <MotiView from={{scale: 1}} animate={{scale: [1, 1.5, 1, 1.5, 1]}}>
    <Text>Test</Test>
  </MotiView>

I tested updating reanimated to different versions (even the last one) without luck

While creating a minimal app to reproduce the issue I found that the problem seems to be with the Hermes Engine. If Hermes is turned off the sequences seem to work properly

@nandorojo I created a repo using react-native init to reproduce the issue on iOS (adding only reanimated, moti, and enabling Hermes)

https://github.com/msantang78/MotiSequenceReproduction

I also added an animation with reanimated sequences and they seem to be working fine.

I hope it helps

For reference: I originally reported this on #131, there were other reports #140 #183

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:28 (19 by maintainers)

github_iconTop GitHub Comments

3reactions
nandorojocommented, Jul 21, 2022

just merged @jstheoriginal’s PR, thanks for your patience here. will release it in the next version

3reactions
jstheoriginalcommented, May 26, 2022

this patch-package diff resolves the issue (extracted function and marked it as a worklet).

diff --git a/node_modules/@motify/core/src/use-map-animate-to-style.ts b/node_modules/@motify/core/src/use-map-animate-to-style.ts
index dce4aa1..9cda484 100644
--- a/node_modules/@motify/core/src/use-map-animate-to-style.ts
+++ b/node_modules/@motify/core/src/use-map-animate-to-style.ts
@@ -220,6 +220,64 @@ function animationConfig<Animate>(
   }
 }
 
+// this used to be an inline function, but it caused the error outlined here:
+// https://github.com/nandorojo/moti/issues/195
+const getSequenceArray = (
+  sequenceKey: string,
+  sequenceArray: SequenceItem<any>[],
+  delayMs: number,
+  config: {},
+  animation: (...props: any) => any,
+  callback: (completed: boolean, value?: any) => void
+) => {     
+  'worklet'
+  
+  const sequence: any[] = []
+
+  for (const step of sequenceArray) {
+    const shouldPush =
+      typeof step === 'object'
+        ? step && step?.value != null && step?.value !== false
+        : step != null && step !== false
+    if (shouldPush) {
+      let stepDelay = delayMs
+      let stepValue = step
+      let stepConfig = Object.assign({}, config)
+      let stepAnimation = animation
+
+      if (typeof step === 'object') {
+        // not allowed in Reanimated: { delay, value, ...transition } = step
+        const stepTransition = Object.assign({}, step)
+
+        delete stepTransition.delay
+        delete stepTransition.value
+
+        const { config: inlineStepConfig, animation } = animationConfig(
+          sequenceKey,
+          stepTransition
+        )
+
+        stepConfig = Object.assign({}, stepConfig, inlineStepConfig)
+        stepAnimation = animation
+
+        if (step.delay != null) {
+          stepDelay = step.delay
+        }
+        stepValue = step.value
+      }
+
+      const sequenceValue = stepAnimation(stepValue, stepConfig, callback)
+      if (stepDelay != null) {
+        sequence.push(withDelay(stepDelay, sequenceValue))
+      } else {
+        sequence.push(sequenceValue)
+      }
+    }
+  }
+
+  return sequence
+}
+
 export function useMotify<Animate>({
   animate: animateProp,
   from: fromProp = false,
@@ -385,55 +443,6 @@ export function useMotify<Animate>({
         continue
       }
 
-      const getSequenceArray = (
-        sequenceKey: string,
-        sequenceArray: SequenceItem<any>[]
-      ) => {
-        const sequence: any[] = []
-
-        for (const step of sequenceArray) {
-          const shouldPush =
-            typeof step === 'object'
-              ? step && step?.value != null && step?.value !== false
-              : step != null && step !== false
-          if (shouldPush) {
-            let stepDelay = delayMs
-            let stepValue = step
-            let stepConfig = Object.assign({}, config)
-            let stepAnimation = animation
-            if (typeof step === 'object') {
-              // not allowed in Reanimated: { delay, value, ...transition } = step
-              const stepTransition = Object.assign({}, step)
-
-              delete stepTransition.delay
-              delete stepTransition.value
-
-              const { config: inlineStepConfig, animation } = animationConfig(
-                sequenceKey,
-                stepTransition
-              )
-
-              stepConfig = Object.assign({}, stepConfig, inlineStepConfig)
-              stepAnimation = animation
-
-              if (step.delay != null) {
-                stepDelay = step.delay
-              }
-              stepValue = step.value
-            }
-
-            const sequenceValue = stepAnimation(stepValue, stepConfig, callback)
-            if (stepDelay != null) {
-              sequence.push(withDelay(stepDelay, sequenceValue))
-            } else {
-              sequence.push(sequenceValue)
-            }
-          }
-        }
-
-        return sequence
-      }
-
       if (key === 'transform') {
         if (!Array.isArray(value)) {
           console.error(
@@ -448,7 +457,7 @@ export function useMotify<Animate>({
 
             if (Array.isArray(transformValue)) {
               // we have a sequence in this transform...
-              const sequence = getSequenceArray(transformKey, transformValue)
+              const sequence = getSequenceArray(transformKey, transformValue, delayMs, config, animation, callback)
 
               if (sequence.length) {
                 let finalValue = withSequence(sequence[0], ...sequence.slice(1))
@@ -484,8 +493,7 @@ export function useMotify<Animate>({
         }
       } else if (Array.isArray(value)) {
         // we have a sequence
-        const sequence = getSequenceArray(key, value)
+        const sequence = getSequenceArray(key, value, delayMs, config, animation, callback)
         let finalValue = withSequence(sequence[0], ...sequence.slice(1))
         if (shouldRepeat) {
           finalValue = withRepeat(finalValue, repeatCount, repeatReverse)

Read more comments on GitHub >

github_iconTop Results From Across the Web

Sequences not working · Issue #140 · nandorojo/moti - GitHub
It looks like there is an issue with sequences since reanimated 2.3. I've heard from a few other people. I'll try to debug...
Read more >
Reanimated 2 failed to create a worklet, maybe you forgot to ...
I was having the same problem today, turns out my babel config didn't contain plugins: ['react-native-reanimated/plugin'], , so it worked after ...
Read more >
Events | React Native Reanimated - Software Mansion
Now all we have to do is to use the useAnimatedStyle hook in order to map the pressed shared value state to the...
Read more >
Reanimated - Expo Documentation
Reanimated uses React Native APIs that are incompatible with "Remote JS Debugging" for JavaScriptCore. In order to use a debugger with your app...
Read more >
Transforms | Moti
If you're using multiple transforms, be sure to retain their order inside of each prop ... This only works with Reanimated 2.3.0 +....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found