I'm using React Native Gesture Handler into a js file and when I run the code I receive this error
ERROR [react-native-gesture-handler] Some of the callbacks in the gesture are worklets and some are not. Either make sure that all calbacks are marked as 'worklet' if you wish to run them on the UI thread or use '.runOnJS(true)' modifier on the gesture explicitly to run all callbacks on the JS thread.
CODE:
` import * as React from 'react'; import { View, Text, Dimensions } from 'react-native'; import styles from '../styles/style_home' import * as Animatable from 'react-native-animatable' import {Canvas, Path, Skia} from '@shopify/react-native-skia'; import {curveBasis, line, scaleLinear, scalePoint} from 'd3'; import DataPalmas from '../../assets/csvjson.json' import Gradient from './Gradient' import XAxisText from './XAxisText'; import { clamp, runOnJS, useSharedValue, withDelay, withTiming } from 'react-native-reanimated'; import Cursor from './Cursor' import { Gesture, GestureDetector, PanGestureHandlerEventPayload, } from 'react-native-gesture-handler'; import {getYForX, parse} from 'react-native-redash';
export default function () {
const [showCursor, setShowCursor] = React.useState(false)
const animationLine = useSharedValue(0)
const animationGradient = useSharedValue({x: 0, y: 0})
const cx = useSharedValue(0)
const cy = useSharedValue(0)
React.useEffect(() => {
animationLine.value = withTiming(1, {duration:2000})
animationGradient.value = withDelay(2000, withTiming({x: 0, y: chartHeight}, {duration: 1000}))
}, [])
const chartHeight = 150
const chartWidth = Dimensions.get('window').width
const chartMargin = 20
const data = DataPalmas
const xDomain = data.map((dataPoint) => dataPoint.Data)
const xRange = [chartMargin, chartWidth - chartMargin]
const x = scalePoint().domain(xDomain).range(xRange).padding(0)
const stepX = x.step()
const max = Math.max(...data.map(val => val.Precipitacao))
const min = Math.min(...data.map(val => val.Precipitacao))
const yDomain = [min, max]
const yRange = [chartHeight, 0]
const y = scaleLinear().domain(yDomain).range(yRange)
const curvedLine = line()
.x(d => x(d.Data))
.y(d => y(d.Precipitacao))
.curve(curveBasis)(data)
const linePath = Skia.Path.MakeFromSVGString(curvedLine)
const path = parse(linePath.toSVGString())
function handleGestureEvent(e){
const clampValue = clamp(
Math.floor(e.absoluteX / stepX) * stepX + chartMargin,
chartMargin,
chartWidth - chartMargin,
)
cx.value = clampValue
cy.value = getYForX(path, Math.floor(clampValue))
}
const pan = Gesture.Pan()
.onTouchesDown(() => {
setShowCursor(true)
})
.onTouchesUp(() => {
setShowCursor(false)
})
.onBegin(handleGestureEvent)
.onChange(handleGestureEvent)
return (
<Animatable.View style={styles.container__graphic} animation={"fadeInLeft"}>
<GestureDetector gesture={pan}>
<Canvas
style={{
width: chartWidth,
height: chartHeight+30,
}}>
<Path
path={linePath}
style={'stroke'}
strokeWidth={2}
color={'#0bb861'}
strokeCap={'round'}
start={0}
end={animationLine}/>
<Gradient
chartHeight = {chartHeight}
chartMargin = {chartMargin}
chartWidth = {chartWidth}
curvedLine = {curvedLine}
animationGradient = {animationGradient}
/>
{data.map((dataPoint, index) => (
<XAxisText
x={x(dataPoint.Data)}
y={chartHeight}
text={dataPoint.Data}
key={index}
/>
))}
{showCursor &&
<Cursor
cx = {cx}
cy = {cy}
chartHeight = {chartHeight}
/>}
</Canvas>
</GestureDetector>
</Animatable.View>
);
}`
When I use 'worklet' into this function the app crashes when I click
function handleGestureEvent(e){
**'worklet'**
const clampValue = clamp(
Math.floor(e.absoluteX / stepX) * stepX + chartMargin,
chartMargin,
chartWidth - chartMargin,
)
cx.value = clampValue
cy.value = getYForX(path, Math.floor(clampValue))
}
You need to add .runOnJS(true)
to your Gesture.Pan()
call, like this:
const pan = Gesture.Pan()
.runOnJS(true)
.onTouchesDown(() => {
setShowCursor(true)
})
.onTouchesUp(() => {
setShowCursor(false)
})
.onBegin(handleGestureEvent)
.onChange(handleGestureEvent)