I have an Expo app where I have an element. I want to call an async function when I double tap that element. For doing that, I found the react-native-gesture-handler library. I wrapped the whole component in a <GestureHandlerRootView> as the docs said, getting the code below. However, the async function editUserTask(), which is defined in another file, doesn't even run here when I double tap. Why is that? I've seen several ideas about using runOnJS(), but VS Code tells me it is deprecated. Any solutions?
// import...
import {
Gesture,
GestureDetector,
GestureHandlerRootView,
} from "react-native-gesture-handler";
export default function Todo() {
<GestureHandlerRootView>
// ...
userTasks[0]?.map((pendingUserTask, index) => {
const doubleTap = Gesture.Tap()
.numberOfTaps(2)
.onStart(() => {
async () => {
await editUserTask({
id: pendingUserTask.id,
title: pendingUserTask.title,
description: pendingUserTask.description,
deadline: pendingUserTask.deadline.toDate(),
user_id: pendingUserTask.user_id as never,
done: true,
tags: pendingUserTask.tags,
});
console.log("A");
};
});
return (
<GestureDetector key={`pending-${index}`} gesture={doubleTap}>
<View collapsable={false}>
<TaskElement
userTask={pendingUserTask}
fetchTasksFunction={fetchUserTasks}
openTaskModalFunction={openTaskModal}
/>
</View>
</GestureDetector>
</GestureHandlerRootView>
}
Your async function is not running because you arre defining an async function but never calling it, and gesture callbacks run on a UI worklet thread, which cant directly execute normal async JS. That is why you must use runOnJS (it’s not deprecated just make sure it comes from react-native-reanimated). The fix is to move your async logic into a normal function and trigger it via runOnJS inside the double-tap gesture.
import {
Gesture,
GestureDetector,
GestureHandlerRootView,
} from "react-native-gesture-handler";
import { runOnJS } from "react-native-reanimated";
const handleDoubleTap = async (task: any) => {
await editUserTask({
id: task.id,
title: task.title,
description: task.description,
deadline: task.deadline.toDate(),
user_id: task.user_id as never,
done: true,
tags: task.tags,
});
console.log("A");
};
const doubleTap = Gesture.Tap()
.numberOfTaps(2)
.onStart(() => {
runOnJS(handleDoubleTap)(pendingUserTask);
});
return (
<GestureHandlerRootView>
<GestureDetector gesture={doubleTap}>
<View collapsable={false}>
<TaskElement userTask={pendingUserTask} />
</View>
</GestureDetector>
</GestureHandlerRootView>
);