Non-Native and Native Animated Values in React Native

Andi Gu
2 min readAug 13, 2017

--

I stumbled on this problem when I was building my parallax tab component (which I wrote about here). The problem is as follows: you have multiple attributes which rely on the scroll progress of a scrollview. Some may be supported by the native driver (such as transform, or opacity), or they may be unsupported as of yet (such as background colour, or text colour). However, the react native scrollview forces you to choose between using the native driver or not using it. Your first instinct may be to choose the ‘non-native’ driver, since it is supported by all properties. However, by foregoing the native driver, you sacrifice the amazing performance of the native animated driver.

The Solution

Simply use both the native and non-native variables! To do this, you must first listen for scroll events with the native driver:

<Animated.ScrollView onScroll={Animated.event([{
nativeEvent: {
contentOffset: {
y: this.nativeScroll
}
}
}], {useNativeDriver: true})} scrollEventThrottle={5}>
{/*content*/}
</Animated.ScrollView>

However, in order to subscribe both the native and non-native scroll, you must add a second ‘listener’ of sorts:

this.nativeScroll.addListener(Animated.event([{value: this.nonNativeScroll}], {useNativeDriver: false}));

How does this work?

Calling Animated.event can actually return two things, depending on whether or not you set useNativeDriver. When useNativeDriver is set to true, it returns this:

This is an object.

However, when this is set to false, it returns the following:

This is a function, and it seems as if it can be called with new values for the animated value. You can actually test this yourself by calling Animated.event([{value: this.nonNativeScroll}], {useNativeDriver: false})(newValue), and your animated variable will go to this new value.

Since we know how to update non-native animated values, but not how to update native animated values, we should allow the react native framework to update the native animated values for us (by passing it in as props to the scrollview). Then, we can update the non-native animated values ourselves by adding a listener as shown above.

Demo

To show how this can be done effectively, I’ve built a simple demo with a view both translates horizontally and changes colours when a user scrolls:

All animations run at 60fps!

The code for this is available below:

--

--