Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native scheduleOnRN Causing Android Crash

I noticed that runOnJS is deprecated in "react-native-worklets": "0.5.1". ESLint keeps hinting me concerning this deprecation and I can't move on unless I disable eslint for the line (which is not best practice).

import { runOnJS } from 'react-native-worklets';

And this is how I use it and working with no problem:

  const handleSlideInNewPosition = useCallback(
    (newPositionsParams: {
      currentOffScreen: number;
      onScreenValue: number;
    }): void => {
      const { currentOffScreen, onScreenValue } = newPositionsParams;

      setContent({ actions, message, severity });
      latestPositionRef.current = position;

      translateY.value = withTiming(onScreenValue, {
        duration: ANIMATION_DUREATION,
        easing: Easing.out(Easing.cubic),
      });

      if (!isPersistent) {
        timerIdRef.current = setTimeout(() => {
          translateY.value = withTiming(
            currentOffScreen,
            { duration: ANIMATION_DUREATION, easing: Easing.in(Easing.cubic) },
            (isFinished) => {
              if (isFinished) {
                runOnJS(() => { // <--- JUST BOTHER THIS SCOPE
                  setMounted(false);
                  hideToaster();
                });
              }
            },
          );
        }, duration);
      }
    },
    [
      actions,
      duration,
      hideToaster,
      isPersistent,
      latestPositionRef,
      message,
      position,
      setContent,
      setMounted,
      severity,
      timerIdRef,
      translateY,
    ],
  );

But then I open the file in the node modules to read about the replacement for runOnJS. It says:

 * @param fun - A reference to a function you want to execute on the JavaScript
 *   thread from the UI thread.
 * @returns A function that accepts arguments for the function passed as the
 *   first argument.
 * @see https://docs.swmansion.com/react-native-worklets/docs/threading/runOnJS
 */
/** @deprecated Use `scheduleOnRN` instead. */
export function runOnJS<Args extends unknown[], ReturnValue>(

So I replace runOnJS with that scheduleOnRN:

import { scheduleOnRN } from 'react-native-worklets';

              ...
              if (isFinished) {
                scheduleOnRN(() => {
                  setMounted(false);
                  hideToaster();
                });
              }
              ...

That doesn't leave ESLint error hint anymore but... EVERYTIME THAT GETS INVOKED, MY APP ON ANDROID EMULATOR QUITS! However, that doesn't cause issue on web.

Even when I simply run it with empty function, it crashes the same:

import { scheduleOnRN } from 'react-native-worklets';

              ...
              if (isFinished) {
                scheduleOnRN(() => {
                });
              }
              ...

The log from adb logcat:

09-26 07:31:52.589 25933 25933 F libc : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x394d28b2cca5d879 in tid 25933 (st.exp.exponent), pid 25933 (st.exp.exponent)

This is my React Native Setup relevant to this issue:

  • "react-native": "0.81.4"
  • "expo": "~54.0.10",
  • "react-native-worklets": "0.5.1"
  • "react-native-reanimated": "~4.1.0"

I run on Android emulator:

  • Expo Go 54.0.5
  • emulator -avd Pixel_9 54.0.4
  • Android Studio: Narwhal 3 Feature Drop | 2025.1.3 Build #AI-251.26094.121.2513.14007798, built on August 28, 2025 Runtime: OpenJDK 64-Bit Server VM (21.0.7 aarch64) by JetBrains OS: macOS 14.3
  • Android Debug Bridge version 1.0.41 Version 36.0.0-13206524 Running on Darwin 23.3.0 (arm64)
like image 497
Herza Islad Avatar asked Dec 22 '25 22:12

Herza Islad


1 Answers

I had the same issue, but I found a way to make it work.

If I use it like this, may App (on iOS) crashes:

position.value = withTiming(-300, { duration: 100 }, (finished) => {
    if (finished) {
       scheduleOnRN(() => onDelete(item.key));  // like a callback
    }
})

But if I use it like this, it works:

position.value = withTiming(-300, { duration: 100 }, (finished) => {
    if (finished) {
        scheduleOnRN(onDelete, item.key);
    }
})

scheduleOnRN takes a function as the first param, and the follow up params are the arguments that will be passed down to that function.

:-)

howEver I dont fully trust it now, so I wrapped it in a try catch block to be sure:


 position.value = withTiming(-300, { duration: 100 }, (finished) => {
     if (finished) {
         try {
              scheduleOnRN(onDelete, item.key);
         } catch (err) {
              console.warn('could not delete item:', item.key, '- Error: ', err)
         }
     }
 })


like image 176
Migalejo Lejo Avatar answered Dec 24 '25 10:12

Migalejo Lejo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!