From dac030df40a14ce15be7186aa2256e3999efefc7 Mon Sep 17 00:00:00 2001 From: Tomek Zawadzki Date: Mon, 7 Aug 2023 14:55:30 +0200 Subject: [PATCH] Add `setNativeProps` helper function on UI runtime (#4595) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Currently, there is no way to update props from a worklet imperatively (except for calling JSI bindings `_updatePropsPaper` or `_updatePropsFabric` directly, but they are implementation-detail and meant to be private). This PR adds `setNativeProps` helper function available on the UI runtime which accepts an animated ref (created with `useAnimatedRef()`) along with a plain JS object with props to be updated. At the moment, both Paper and Fabric is supported as well as basic web support works. Proper web support is doable but requires a refactor of `useAnimatedRef`. ## Test plan `SetNativePropsExample.tsx` 🆕 --- app/src/examples/SetNativePropsExample.tsx | 70 +++++++++++++++++++++ app/src/examples/index.ts | 20 +++--- src/reanimated2/Colors.ts | 31 +++++++++ src/reanimated2/NativeMethods.ts | 2 +- src/reanimated2/SetNativeProps.ts | 59 +++++++++++++++++ src/reanimated2/UpdateProps.ts | 29 +-------- src/reanimated2/animation/styleAnimation.ts | 3 +- src/reanimated2/hook/useAnimatedRef.ts | 16 ++++- src/reanimated2/index.ts | 1 + 9 files changed, 192 insertions(+), 39 deletions(-) create mode 100644 app/src/examples/SetNativePropsExample.tsx create mode 100644 src/reanimated2/SetNativeProps.ts diff --git a/app/src/examples/SetNativePropsExample.tsx b/app/src/examples/SetNativePropsExample.tsx new file mode 100644 index 00000000000..d3ae75960ab --- /dev/null +++ b/app/src/examples/SetNativePropsExample.tsx @@ -0,0 +1,70 @@ +import Animated, { + runOnJS, + setNativeProps, + useAnimatedRef, +} from 'react-native-reanimated'; +import { Button, StyleSheet } from 'react-native'; +import { + Gesture, + GestureDetector, + GestureHandlerRootView, + TextInput, +} from 'react-native-gesture-handler'; + +import React from 'react'; + +const AnimatedTextInput = Animated.createAnimatedComponent(TextInput); + +function delay(ms: number) { + const start = performance.now(); + while (performance.now() - start < ms) {} +} + +export default function SetNativePropsExample() { + const [text, setText] = React.useState('Hello'); + + const animatedRef = useAnimatedRef(); + + const send = () => { + delay(500); + console.log('SEND', text); + setText(''); // calling setText affects the JS state but doesn't update the native view + }; + + const tap = Gesture.Tap().onEnd(() => { + 'worklet'; + setNativeProps(animatedRef, { + text: '', + backgroundColor: `hsl(${Math.random() * 360}, 100%, 50%)`, + }); + runOnJS(send)(); + }); + + return ( + + + +