nandorojo/moti

Runtime crash if easing is used within useAnimationState, error: '[Reanimated] The easing function is not a worklet. Please make sure you import `Easing` from react-native-reanimated.'

Opened this issue · 0 comments

Is there an existing issue for this?

  • I have searched the existing issues

Do you want this issue prioritized?

  • Yes, I have sponsored
  • Not urgent

Current Behavior

Hey Fernando,
thanks for your awesome work.
I noticed a crash after updating RN, expo, reanimated und moti.
The app is crashing the error '[Reanimated] The easing function is not a worklet. Please make sure you import Easing from react-native-reanimated.'
This is triggered by a transitionTo() call from useAnimationState().

Its failing because of reanimated runtime validations created in (src/reanimated2/animation/util.ts) PR: software-mansion/react-native-reanimated#5639 and released with reanimated 3.9.0 .

Expected Behavior

To pass the easing runtime validation from reanimated

Steps To Reproduce

Minimal Reproduction:

  1. Copy code and render the component (default export)
  2. Press the red or blue Box
  3. App will crash after 2 clicks

Versions

- Moti: 0.29.0
- Reanimated: 3.11.0
- React Native: 0.74.1
(latest as of now)

Screenshots

No response

Reproduction

The Error happens only on bare RN projects and on the moti/examples/sample expo project.
Could not reproduce it on Snack.

Removing the
node_modules/react-native-reanimated/src/reanimated2/animation/util.ts

import React, {useCallback, useState} from 'react'
import {Pressable, StyleSheet} from 'react-native'
import {useAnimationState, View} from 'moti'
import {Easing} from 'react-native-reanimated';

const useFadeInRight = () => {
  return useAnimationState({
    fadeInRight: {
      opacity: [
        {value: 0, duration: 0},
        {value: 1, duration: 500, delay: 0, type: 'timing'},
      ],
      translateX: [
        {value: 100, duration: 0},
        // TODO: if you put easing here, reanimated throws a error (because a runtime validation fails):
        {value: 0, duration: 500, delay: 0, type: 'timing', easing: Easing.inOut(Easing.exp)},

      ],
    },
  })
};

// Press the red/blue Box to crash the App
function CrashExample() {
  const fadeInDown = useFadeInRight()

  const triggerAnimation = useCallback(() => {
    fadeInDown.transitionTo('fadeInRight');
    setIsEnabled(old => !old)
  }, [fadeInDown]);

  const [isEnabled, setIsEnabled] = useState(false)

  return (
    <View
      style={styles.shape}
      state={fadeInDown} transition={{duration: 500, type: 'timing', easing: Easing.inOut(Easing.exp)}}
    ><Pressable onPress={triggerAnimation}>{
      isEnabled ? (
        <View style={{width: 100, height: 100, backgroundColor: 'red'}}></View>) : (
        <View style={{width: 100, height: 100, backgroundColor: 'blue'}}></View>)
    }</Pressable>
    </View>

  )
}

export default function Container() {
  return (
    <View style={styles.container}>
      <CrashExample/>
    </View>
  )
}

const styles = StyleSheet.create({
  shape: {
    justifyContent: 'center',
    height: 250,
    width: 250,
    borderRadius: 25,
    marginRight: 10,
    backgroundColor: 'black',
  },
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    flexDirection: 'row',
    backgroundColor: 'cyan',
  },
})