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.

Tried to synchronously call function {parseISO} from a different thread - but it's marked as a worklet?

See original GitHub issue

Description

Marking function as worklet but it still tries to call it on the JS thread

Expected behavior

It will run on the UI thread

Actual behavior & steps to reproduce

Try out the snack (will not show logs or the error)

or pull down the example repo try it locally (will show logs and error)

simulator_screenshot_9F3A86CA-C246-4BE0-8274-B6E912A8BEDE

Snack or minimal code example

https://github.com/Norfeldt/worklet-example/blob/main/App.tsx

https://snack.expo.dev/@nord_investments/worklet-example

import React, { useEffect } from 'react';
import { StyleSheet, View, Text } from 'react-native';
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
  withRepeat,
  useAnimatedGestureHandler,
} from 'react-native-reanimated';
import {
  Gesture,
  GestureDetector,
  GestureHandlerRootView,
} from 'react-native-gesture-handler';
import { ReText } from 'react-native-redash';
import { format, parseISO } from 'date-fns'

const someWorklet = (year: string, displayFormat = 'dd.MM.yyyy') => {
  'worklet';

  console.log('worklet log');
  const formattedDate = format(parseISO(`${year}-01-01`), displayFormat);

  return formattedDate;
};

export default function App() {
  const year = useSharedValue('2022');
  const randomDate = useSharedValue('N/A');

  const tapGesture = Gesture.Tap().onStart(() => {
    console.log('getsture logging');
    randomDate.value = someWorklet(year.value);
  });

  return (
    <View style={styles.container}>
      <GestureHandlerRootView style={styles.gestureArea}>
        <GestureDetector gesture={tapGesture} style={styles.gestureArea}>
          <Animated.View style={styles.gestureArea}>
            <Text>Static Text</Text>
            <ReText text={randomDate} style={styles.text} />
          </Animated.View>
        </GestureDetector>
      </GestureHandlerRootView>
    </View>
  );
}

Package versions

name version
react-native 0.64.3
react-native-reanimated ~2.3.1
NodeJS v16.15.1
Xcode N/A
Java N/A
Gradle N/A
expo 44

package.json

{ “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”: { “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-web”: “0.17.1”, “react-native-paper”: “4.9.2”, “@expo/vector-icons”: “^12.0.0”, “expo-constants”: “~13.0.2”, “react-native-reanimated”: “~2.3.1”, “react-native-screens”: “~3.10.1”, “react-native-gesture-handler”: “~2.1.0”, “date-fns”: “^2.28.0”, “react-native-redash”: “^18.0.0” }, “devDependencies”: { “@babel/core”: “^7.12.9”, “@types/react”: “~17.0.21”, “@types/react-native”: “~0.64.12”, “typescript”: “~4.3.5” }, “private”: true, “resolutions”: { “@types/react”: “~17.0.47” } }

Affected platforms

  • Android
  • [ x] iOS
  • Web

Issue Analytics

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

github_iconTop GitHub Comments

2reactions
Norfeldtcommented, Jul 28, 2022

Thank you very much for this great clarification - it’s a great help to me.

0reactions
tomekzawcommented, Jul 26, 2022

Is it correctly understood that a shared value is only initially “shared” in a way that it comes from the JS react thread but like react ref there isn’t the same life cycle methods/events that makes react evaluate the virtual DOM every time it changes?

Shared values are completely independent from React, component life cycle, virtual DOM etc. Basically, shared value is just some JS value (number, string, array or object) that you can read and update from both JS contexts, i.e. from RN code and from worklets. In worklets, reading and writing to shared value is synchronous. In regular RN JS code, reading shared value is synchronous (but the result can be outdated) and writing to shared value is asynchronous (i.e. scheduled on the UI thread). Shared values can be used to share some data between these two JS contexts, like width, height or color of some component, and can also be smoothly and precisely animated using withTiming, withSpring etc.

Using how to pass context via RunOnUI I don’t understand how can be archived since the docs uses a worklet as the example and the event comes from the UI thread (pan gesture scroll showing for different dates). Could you elaborate a little more on this approach?

The workaround I have suggested only makes sense when the “update” originates from the main JS context (e.g. after RN component state change, when some network request completes, etc.). In cases when the event originates from the UI thread (i.e. when using Gesture Handler), we would like to handle it on the UI thread so the app feels responsive. Otherwise, we would block the UI thread until JS context completes our function call.

In the specific case of showing different dates depending on pan gesture scroll, I would recommend implementing the formatting function as a worklet on your own.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Tried to synchronously call function {w} from a different thread
You're calling "finishAnimation" from the onEnd callback. That could be a problem, since finishAnimation isn't a worklet.
Read more >
runOnJS | React Native Reanimated
When you call a function on the UI thread you can't be sure if you're calling a worklet or a callback from the...
Read more >
Practical Web Development with Haskell
Ecky Putrady is a software engineer with extensive experience in developing web applications. Specializing in Java, Ecky discovered Haskell four years ago ...
Read more >
How to have synchronous function calls with ...
Is there a way to make the call synchronously using WKScriptMessageHandler , i.e. calling a C# method from JavaScript and stop the execution ......
Read more >
Practical Web Development With Haskell Master The Essential ...
While the advice and information in this book are believed to be true and ... have imported ClassyPrelude) will run two actions on...
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