nandorojo / moti

🐼 The React Native (+ Web) animation library, powered by Reanimated 3.
https://moti.fyi
MIT License
3.9k stars 120 forks source link

Degrees/radians become undefined when repeating a rotate transition #227

Closed clayrisser closed 1 year ago

clayrisser commented 1 year ago

Is there an existing issue for this?

Current Behavior

I have put the details for this on issue #217. I can close this issue once #217 is reopened.

Expected Behavior

No response

Steps To Reproduce

afds

Versions

Moti: 0.18.0
Reanimated: 2.5.0
React Native: 0.68.0

Screenshots

No response

Reproduction

http://localhost:6006/?path=/story/components-spinner--with-back-ground

nandorojo commented 1 year ago

Your reproduction URL is a local URL fyi.

clayrisser commented 1 year ago

Oh, sorry, meant to provide the following url.

https://risserlabs.gitlab.io/community/native-theme-ui/?path=/story/components-spinner--like-theme-ui

I'm going to debug it a bit more and if I still can't figure out the issue I'll create an Expo snack.

clayrisser commented 1 year ago

Ok, I found where the bug is coming from, but I have no idea why. I don't even know if it's an issue with Moti or an issue with react native reanimated.

Basically, the value parameter in the onStart(animation, value, now, previousAnimation) function in withRepeat is "undefined" sometimes. And no, it is not undefined, but the string "undefined". Sometimes it is "undefinedNaN" instead. This means somehow somewhere the toString() function is called on an undefined and/or NaN value. I have no idea where that is happening.

https://github.com/software-mansion/react-native-reanimated/blob/main/src/reanimated2/animation/repeat.ts#L74

As for a temporary solution, I patched the reanimated2/animation/repeat.ts file with the following patch and it fixed the issue.

if (!value || value.toString().indexOf('undefined') > -1) value = 0;

This seems like a band-aid fix, but it seems to work well for now. Maybe this is useful if anyone else is facing this issue.

Here is the full patch.

diff --git a/lib/reanimated2/animation/repeat.js b/lib/reanimated2/animation/repeat.js
index 3ca0bed4b62ea6ffb99e4a5a5e8578d7d747048e..5132355ec6f34b9994c9dcf225209a95c8049ed6 100644
--- a/lib/reanimated2/animation/repeat.js
+++ b/lib/reanimated2/animation/repeat.js
@@ -39,6 +39,7 @@ export function withRepeat(_nextAnimation, numberOfReps = 2, reverse = false, ca
             }
         };
         function onStart(animation, value, now, previousAnimation) {
+            if (!value || value.toString().indexOf('undefined') > -1) value = 0;
             animation.startValue = value;
             animation.reps = 0;
             nextAnimation.onStart(nextAnimation, value, now, previousAnimation);
diff --git a/src/reanimated2/animation/repeat.ts b/src/reanimated2/animation/repeat.ts
index 4dfb11fcf2ab3ce78f0df3e1cf702ca124eb1d28..0be1168b09152c5f3a6a59e8c4d4eae579a57fa7 100644
--- a/src/reanimated2/animation/repeat.ts
+++ b/src/reanimated2/animation/repeat.ts
@@ -75,6 +75,7 @@ export function withRepeat(
       now: Timestamp,
       previousAnimation: RepeatAnimation
     ): void {
+      if (!value || value.toString().indexOf('undefined') > -1) value = 0;
       animation.startValue = value;
       animation.reps = 0;
       nextAnimation.onStart(nextAnimation, value, now, previousAnimation);

I am using react-native-reanimated version 2.8.0

nandorojo commented 1 year ago

good find. that would certainly be a reanimated issue. could you open an issue / PR there?

clayrisser commented 1 year ago

What would be the best way to open an issue on reanimated, since they will probably want an example that is not using moti?

nandorojo commented 1 year ago

it should be pretty straightforward to recreate it with reanimated. just use useAnimatedStyle and withTiming on Expo snack with Sdk 45

nandorojo commented 1 year ago
import Animated, { useAnimatedStyle, withTiming, useSharedValue } from 'react-native-reanimated'

export default function App() {
  const rotate = useSharedValue('0deg')
  const style = useAnimatedStyle(() => ({
    transform: [{ rotate: withTiming(rotate.value) }]
  }))

  const onPress = () => {
     rotate.value = rotate.value == '0deg' ? '360deg' : '0deg'
  }

  return <Animated.View style={style} />
}

Does this give you what you need? Would like to close this out or find a fix ideally. Thanks @clayrisser!

dev-andremonteiro commented 1 year ago

Do you know if this is fixed in the current version of reanimated ? I couldn't find any issues from @clayrisser in react-native-reanimated repository, should I create an issue regarding this ?