-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
setNativeProps
helper function on UI runtime (#4595)
<!-- Thanks for submitting a pull request! We appreciate you spending the time to work on these changes. Please follow the template so that the reviewers can easily understand what the code changes affect. --> ## 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` 🆕
- Loading branch information
Showing
9 changed files
with
192 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<TextInput>(); | ||
|
||
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 ( | ||
<GestureHandlerRootView style={styles.container}> | ||
<AnimatedTextInput | ||
value={text} | ||
onChangeText={setText} | ||
style={styles.input} | ||
ref={animatedRef} | ||
autoFocus | ||
/> | ||
<GestureDetector gesture={tap}> | ||
<Button title="Send" /> | ||
</GestureDetector> | ||
</GestureHandlerRootView> | ||
); | ||
} | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
flex: 1, | ||
alignItems: 'center', | ||
justifyContent: 'center', | ||
}, | ||
input: { | ||
width: 250, | ||
padding: 3, | ||
borderWidth: 1, | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { ShadowNodeWrapper, StyleProps } from './commonTypes'; | ||
import { | ||
isChromeDebugger, | ||
isJest, | ||
isWeb, | ||
shouldBeUseWeb, | ||
} from './PlatformChecker'; | ||
|
||
import type { AnimatedRef } from './hook/commonTypes'; | ||
import type { Component } from 'react'; | ||
import { _updatePropsJS } from './js-reanimated'; | ||
import { processColorsInProps } from './Colors'; | ||
|
||
const IS_NATIVE = !shouldBeUseWeb(); | ||
|
||
export let setNativeProps: <T extends Component>( | ||
animatedRef: AnimatedRef<T>, | ||
updates: StyleProps | ||
) => void; | ||
|
||
if (isWeb()) { | ||
setNativeProps = (_animatedRef, _updates) => { | ||
const component = (_animatedRef as any)(); | ||
_updatePropsJS(_updates, { _component: component }); | ||
}; | ||
} else if (IS_NATIVE && global._IS_FABRIC) { | ||
setNativeProps = (animatedRef, updates) => { | ||
'worklet'; | ||
const shadowNodeWrapper = (animatedRef as any)() as ShadowNodeWrapper; | ||
processColorsInProps(updates); | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
_updatePropsFabric!([{ shadowNodeWrapper, updates }]); | ||
}; | ||
} else if (IS_NATIVE) { | ||
setNativeProps = (animatedRef, updates) => { | ||
'worklet'; | ||
const tag = (animatedRef as any)() as number; | ||
const name = (animatedRef as any).viewName.value; | ||
processColorsInProps(updates); | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
_updatePropsPaper!([{ tag, name, updates }]); | ||
}; | ||
} else if (isChromeDebugger()) { | ||
setNativeProps = () => { | ||
console.warn( | ||
'[Reanimated] setNativeProps() is not supported with Chrome Debugger.' | ||
); | ||
}; | ||
} else if (isJest()) { | ||
setNativeProps = () => { | ||
console.warn('[Reanimated] setNativeProps() is not supported with Jest.'); | ||
}; | ||
} else { | ||
setNativeProps = () => { | ||
console.warn( | ||
'[Reanimated] setNativeProps() is not supported on this configuration.' | ||
); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters