Reanimated
Unistyles works seamlessly with react-native-reanimated
. Learn best practices for combining both libraries.
Access theme in worklets
Using the theme from UnistylesRuntime.getTheme()
will not trigger worklet updates. Importing it from useUnistyles
will cause a re-render.
That’s why to use Unistyles theme in worklets (e.g. in useAnimatedStyle
), you need to import a special hook from react-native-unistyles/reanimated
.
import { useAnimatedTheme } from 'react-native-unistyles/reanimated'import Animated, { useAnimatedStyle, interpolate } from 'react-native-reanimated'
export const MyAnimatedComponent = () => { const theme = useAnimatedTheme() const style = useAnimatedStyle(() => ({ backgroundColor: theme.value.colors.background, // other animated styles }))
return ( <Animated.View style={style} /> )}
Animating variant colors
Starting from RC.5, it’s possible to reuse Unistyles variant colors and animate them using the useAnimatedStyle
hook.
Define your variants with a color
property:
const styles = StyleSheet.create((theme, rt) => ({ styleWithVariants: { height: 100, width: 100, variants: { variant: { red: { backgroundColor: theme.colors.primary }, blue: { backgroundColor: theme.colors.secondary } } } }}))
In this case, styleWithVariants
can transition the backgroundColor
property from primary
to secondary
and vice versa.
Import the useAnimatedVariantColor
hook to animate variant colors:
import { useAnimatedVariantColor } from 'react-native-unistyles/reanimated'
// Select backgroundColor from styles.styleWithVariants (TypeScript will infer all possible color properties)const color = useAnimatedVariantColor(styles.styleWithVariants, 'backgroundColor')const animatedStyle = useAnimatedStyle(() => { return { // color is a SharedValue that can be animated however you want backgroundColor: withTiming(color.value, { duration: 500 }) }})
useAnimatedVariantColor
also respects theme and breakpoint changes and will animate to the new color automatically.
Merging styles
When you want to use Unistyles
styles in Animated
components, never mix them with Reanimated
styles:
import { StyleSheet } from 'react-native-unistyles'import Animated, { useAnimatedStyle } from 'react-native-reanimated'
export const MyAnimatedComponent = () => { const style = useAnimatedStyle(() => ({ ...styles.container, // never do that! 💥 // other animated styles }))
return ( <Animated.View style={style} /> )}
const style = StyleSheet.create(theme => ({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: theme.colors.background, }}))
This will produce a single style with both Unistyles
C++ state and Reanimated
animation metadata, which might cause performance issues at the ShadowTree
level (both libraries will animate and override the same style nodes).
Instead, separate both styles:
import { StyleSheet } from 'react-native-unistyles'import Animated, { useAnimatedStyle } from 'react-native-reanimated'
export const MyAnimatedComponent = () => { const animatedStyles = useAnimatedStyle(() => ({ // animated styles }))
return ( <Animated.View style={[styles.container, animatedStyles]} /> // ✅ Good! )}
const style = StyleSheet.create(theme => ({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: theme.colors.background, }}))
With this approach, both libraries will focus on updating own styles, which will result in better performance.