1

Error The Error I got on my Phone

Im learning react native gesture handler and react native reanimated from the docs. I got this error when i got the gesture coordinates ,passed them to the useShared value translateX. Im running my app on a Samsung Galaxy A5 2017 running android 8.0.0. Please explain your answer.

App.js

// import { StatusBar } from 'expo-status-bar';
import { useEffect } from 'react';
import { StyleSheet, Text, View,StatusBar,TouchableOpacity } from 'react-native';
import Animated, {useSharedValue, useAnimatedStyle, withTiming,withSpring,withRepeat} from 'react-native-reanimated'
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { NavigationContainer } from '@react-navigation/native';
import Header from './components/Header';
import Gesture from './screens/Gesture';
const SimpleAnimation=({navigation})=>{
  const SIZE=100.0
  const handleRotation=(progress)=>{
    "worklet";
    return `${progress.value*2*Math.PI}rad`;
  }
  const progress=useSharedValue(0.5)
  const scale=useSharedValue(0.5)
const reanimatedStyle=useAnimatedStyle(()=>{
return {
  opacity: progress.value,
  transform:[{scale:scale.value},{rotate:handleRotation(progress) }],
  borderRadius:(progress.value*SIZE)/2,
};
},[])
useEffect(()=>{
  progress.value=withRepeat(withSpring(1),-1,true);
  scale.value=withRepeat(withSpring(2),-1,true)
},[]);
  return (
    <View style={{flex:1,marginTop:StatusBar.currentHeight}}>
    <Header LeftComponent={()=>(<Text style={{color:"tomato",fontWeight:"bold",fontSize:20}}>Animation</Text>)} RightComponent={()=>(<TouchableOpacity onPress={()=>navigation.navigate("GestureScreen")} style={{backgroundColor:"tomato",padding:10,borderRadius:10,}}><Text style={{color:"white",fontWeight:"bold"}}>Go To Gestures</Text></TouchableOpacity>)} /> 

  <View style={styles.container}>
      <Animated.View style={[{width:SIZE,height:SIZE,backgroundColor:"blue"},reanimatedStyle]}>
      
      </Animated.View>
    </View>
    </View>
  );
}
const Stack = createNativeStackNavigator();
export default function App() {
 const navigateTo=(screenname)=>{

 }
  return (
    <NavigationContainer>
    <Stack.Navigator initialRouteName='Animation' screenOptions={{headerShown:false}}>
      <Stack.Screen name="Animation" component={SimpleAnimation}/>
      <Stack.Screen name="GestureScreen" component={Gesture}/>
      
    </Stack.Navigator>
  </NavigationContainer> 
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});
   

Gesture.js

import { StyleSheet, Text, View,StatusBar,TouchableOpacity } from 'react-native'
import React from 'react'
import Animated,{useSharedValue,useAnimatedStyle, runOnJS} from 'react-native-reanimated'
import Header from '../components/Header'
import { Gesture,GestureDetector,GestureHandlerRootView } from 'react-native-gesture-handler'

function ActualGesture() {
    const translateX=useSharedValue(0);
    // const translateY=useSharedValue(0);

    const gesture=Gesture.Pan().onUpdate((event)=>{
        translateX=event.translationX;

    });
    const rStyle=useAnimatedStyle(()=>{
        return {    
            transform:[{translateX:translateX.value}],
        };
    });
  return (
    <GestureHandlerRootView style={styles.container}>
      <GestureDetector gesture={gesture}>
     <Animated.View style={[styles.circle,rStyle]}></Animated.View>
     </GestureDetector>
    </GestureHandlerRootView>
  )
}
const GestureScreen = ({navigation}) => {
   
  return (
    <View style={{flex:1,marginTop:StatusBar.currentHeight}}>
    <Header LeftComponent={()=>(<TouchableOpacity onPress={()=>navigation.navigate("Animation")} style={{backgroundColor:"tomato",padding:10,borderRadius:10,}}><Text style={{color:"white",fontWeight:"bold"}}>Return</Text></TouchableOpacity>)} RightComponent={()=>(<TouchableOpacity onPress={()=>navigation.navigate("GestureScreen")} style={{backgroundColor:"tomato",padding:10,borderRadius:10,}}><Text style={{color:"white",fontWeight:"bold"}}>Go To Gestures</Text></TouchableOpacity>)} /> 
    <ActualGesture/>
 
    </View>
  )
}

export default GestureScreen

const styles = StyleSheet.create({
    container: {
      flex: 1,
      backgroundColor: '#fff',
      alignItems: 'center',
      justifyContent: 'center',
    },
    circle:{
        height:60,aspectRatio:1,backgroundColor:"blue",borderRadius:50
    }
  });   

package.json

{
  "name": "animate",
  "version": "1.0.0",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject"
  },
  "dependencies": {
    "@react-navigation/native": "^6.0.8",
    "@react-navigation/native-stack": "^6.5.0",
    "expo": "~44.0.0",
    "expo-status-bar": "~1.2.0",
    "react": "17.0.1",
    "react-dom": "17.0.1",
    "react-native": "0.64.3",
    "react-native-gesture-handler": "~2.1.0",
    "react-native-reanimated": "~2.3.1",
    "react-native-safe-area-context": "3.3.2",
    "react-native-screens": "~3.10.1",
    "react-native-web": "0.17.1"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9"
  },
  "private": true
}

From what i understand from the error is that the gesture function shouldve either been a JS thread or a worklet,i tried doing that to no avail by adding "worklet"; to the beginning of the functions code. Im guessing this is an android error, because based off youtube tutorials given an iOS emulator it works just fine. The gesture function is bringing the right coordinates, its just the changing of the styling to match the translatex value. Please help me i dont know how to carry on from here.

1 Answers1

2

react-native-gesture-handler Gesture can run on js thread with .runOnJS(true) in your case it would be :

function ActualGesture() {
    const translateX=useSharedValue(0);
    // const translateY=useSharedValue(0);

    const gesture=Gesture.Pan().runOnJS(true).onUpdate((event)=>{
        translateX=event.translationX;

    });
    const rStyle=useAnimatedStyle(()=>{
        return {    
            transform:[{translateX:translateX.value}],
        };
    });
  return (
    <GestureHandlerRootView style={styles.container}>
      <GestureDetector gesture={gesture}>
     <Animated.View style={[styles.circle,rStyle]}></Animated.View>
     </GestureDetector>
    </GestureHandlerRootView>
  )
}
Akats
  • 21
  • 1
  • When should we be using runOnJS()? How big is the performance impact when adding this? – Chen W Oct 25 '22 at 18:03
  • You should use it whenever you want to run js code and concerning performance impact, i don't have any idea but keep in mind that runOnUi is asynchronous and runOnJs is not – Akats Oct 26 '22 at 19:34