Skip to content

Reanimated

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.