Jamon and Robin dive into useNativeDriver, the native driver for animations, and explain how it boosts performance and delivers seamless animations in your React Native apps.
This episode is brought to you by Infinite Red! Infinite Red is a premier React Native design and development agency located in the USA. With five years of React Native experience and deep roots in the React Native community (hosts of Chain React and the React Native Newsletter), Infinite Red is the best choice for your next React Native app.
Connect With Us!
Todd Werth:
Welcome back to React Native Radio Podcast, episode 3 0 1 r and r explains native driver for animations.
Jamon Holmgren:
Robin, how often do you turn on the used native driver on the animated module in React Native?
Robin Heinze:
I can't remember a time when I haven't turned on the native driver.
Jamon Holmgren:
Yeah, it's pretty much always on, right?
Robin Heinze:
But I never knew why I was doing it. That's just what all the examples online have it.
Jamon Holmgren:
Yeah, turn it on.
Robin Heinze:
You always use it.
Jamon Holmgren:
Exactly. And of course the animated module is the one that comes with React native and there's Reanimated, which is a third party module by Software Mansion that does a great job and we use it all the time, but of course animated is still important because it's still an important part of the React native ecosystem. Sometimes you don't want to use Reanimated. It's also used by some internal components like Touchable for example. Touchable Opacity will use the animated module to
Robin Heinze:
Yeah, because they animate. What happens when you press in and press out? There's animations happening there, which you don't think about, but there's a lot of animations and built-in components like that.
Jamon Holmgren:
And the React native docs have a pretty good animations guide and animations are important in a lot of apps. I mean, not every app needs animations, but I guess there's a quote in our notes. Did you put this?
Robin Heinze:
I did. So this is from the very first paragraph of the animations guide in the React native docs, which is the best explanation of why you use animations and what they are, and I'm going to read this verbatim because I like it so much. Animations are very important to create a great user experience. Stationary objects must overcome inertia as they start moving objects in motion, have momentum and rarely come to a stop immediately. Animations allow you to convey physically believable motion in your interface, which is so true. That's why we animate so that it feels like how real things in the physical world would move.
Jamon Holmgren:
Okay. It's almost like skew morphic. It's like the early days of the iPhone where they were trying to make it feel like real objects in space. Right,
Robin Heinze:
Exactly.
Jamon Holmgren:
Yeah, that makes sense. You push a button and there's a little bit of an animation as it goes in
Robin Heinze:
And it starts slowly and then click speeds up and then slows down as it comes to a stop because real objects wouldn't just like bam, stop. Must they hit a wall,
Jamon Holmgren:
Right? Yeah. What do you call that? The
Robin Heinze:
Momentum and inertia?
Jamon Holmgren:
Well, it's based on momentum, but there's a word for this. Easing. Easing. We call it easing, yeah.
Robin Heinze:
Yeah. Anyway,
Jamon Holmgren:
So in this r and r explains specifically, we're going to be talking about the native driver for the animated API. Of course, remember r and r Explains is where we drill down into pretty specific aspects of React native and make sure that we can cover as much as possible in the 30 minutes or so that we have here. And really quickly, I do want to also mention that this episode is sponsored by Surprise Infinite Red. Infinite Red is a Premier React native development agency located fully remote in the US and Canada, mostly the US if we're being honest. If you're looking for React native expertise for your next project, hit us up. You'll talk with me on Zoom. You'll probably talk with Gantt, my business partner and Derek, who is also involved in our sales process. So definitely reach out infant Red slash React native.
Jamon Holmgren:
And don't forget to mention at that time that you heard about us through the React Native Radio podcast. We appreciate that. In the docs, it talks about how the animated API was designed with a very important constraint in mind. It's serializable. That means that you can send everything about that animation from the JavaScript side to the native side before it's even started, and that would allow the native code to take over and say, okay, this is what you want me to do. I'll do it. Don't worry. You don't have to manage me. I'm good. I will basically do the animation on the UI thread without having to go through the bridge on every frame. And even if you were like bridge list mode, that could still be a little bit of overhead. So that's essentially, this was designed from the beginning with this sort of thing in mind.
Robin Heinze:
I mean, that's React native right there is doing stuff in JS and then serializing it over the bridge to
Jamon Holmgren:
Native and then having Native do sort of the end
Robin Heinze:
Result do its native thing to make it. It's a native app that you're seeing, but it's JavaScript that told it what to do.
Jamon Holmgren:
What to do. Yeah, exactly. That's React native in a nutshell. So if you just use animated by default, what is it using
Robin Heinze:
By default? It's using js. It's in js, it's using,
Jamon Holmgren:
So it's not doing that. It's not sending it over to the native,
Robin Heinze:
Right? Right. It's not sending it over to native, which is not great for performance because JavaScript is slower than native and you're using the thread that you're also trying to render your app with,
Jamon Holmgren:
And it's essentially doing this request animation frame, which is supposed to run 60 times a second or so, whatever your frame rate is. And then you then would do the calculation of where should this element be or property should it be? And then it's sending it over and saying, Hey, do this thing which uses set native props under the hood, so it's doing it as quickly as it can, but there's still some lag. You're reliant on the JavaScript thread to keep running at 60 frames a second, and it can kind of get hiccupy and glitchy. You'll notice this if you try to use just the JavaScript driver, you'll notice these things popping up, especially in older, slower phones.
Robin Heinze:
Definitely. So why is that even the default? That's what my first question was is if this is not a great experience, why is it the default?
Jamon Holmgren:
Yeah, I had that question as well, and when we looked into it earlier, there are some caveats with the native driver. So the native driver of course, just to talk about that is where the native side is executing the animation. So instead of with JavaScript, instead of having that run every animation frame, it just sends over, I need this all to happen, including with this timing, this animation, this easing, all of those things. It just does it and it will hook back with events. We'll talk a little bit more about events as we get into this, but the caveats are, you can't animate layout properties like Flexbox in position. It doesn't work with pan responder. It does work with scroll views and on scroll and stuff, but it doesn't work with pan responder. When you're using animated event, it will only work with direct events and not bubbling events. That's why Pan responder doesn't work. It requires bubbling events.
Robin Heinze:
Hold up for a second. What are bubbling events? Because that just sounds funny.
Jamon Holmgren:
I'm tempted to make some sort of joke about my kids' birthday parties or something, but I don't know. I can't really pull it off here.
Robin Heinze:
Any toddler birthday party is a bubbling event. It
Jamon Holmgren:
Is, yeah. So we're used to this in web, but if an event happens like a click event, let's say on a child component or dom element, then it will, that click will actually be sent up the hierarchy to its parents. It'll bubble up the hierarchy. You can actually stop it from continuing to bubble up, but it will continue to bubble up if you don't. And so parent events can subscribe to click events that happen to their children. It lets it bubble up. If events do not bubble, then it will only happen on whatever was clicked on or tack on or whatever. So that's what a bubbling event is, and animated event does not do that. Just direct events.
Robin Heinze:
Right. Okay.
Jamon Holmgren:
So that that's a little bit of a limitation as well. It also, when an animation is running, it can also prevent virtualized lists components from rendering more rows and things like that. So there's a way to get around it by turning off interactions in your animations configuration so that you can run that animation while the user is scrolling through a list or something like that. So there are some downsides to using the native driver. Of course, a lot of these things are better with reanimated, but that's outside the scope of what we're going to be talking about here. But the vast majority of the time, you're going to want the native driver to be turned on, so it's not on by default, but it pretty much should be.
Robin Heinze:
It's false by default only for specific compatibility things and because there are caveats that they want people to turn it on with the knowledge that they're turning it on.
Jamon Holmgren:
Yeah, that's right. It's definitely more compatible, has more capability on the JavaScript side, but the performance hit is enough that it just doesn't feel worth it to me. Let's talk about how it works. How does the used native driver, we've talked a little bit about it already, but let's dive into that a little bit. What is happening when you turn on used Native driver?
Robin Heinze:
Well, really what happens is that it sends everything about the animation to the native side and then it runs on the native side. It's not running in JavaScript. It sometimes will pass events back to JavaScript, but it isn't reliant on the JavaScript thread to keep going. It's all running in Kotlin or objective C native code
Jamon Holmgren:
And it's running on the UI thread. And this is important, I think people need to know this. This is more of an iOS thing, but it also applies to Android as well. There is one, so these apps are multithreaded one thread that is designated as the main thread, and it is sometimes you'll hear it called the main queue, and it's the main thread. It's the UI thread. It's where all of the actual rendering is happening. All the drawing is happening.
Robin Heinze:
And so anytime you use that thread for something else, you're going to get stutters in your ui. The user is going to see that there's gaps or flashes.
Jamon Holmgren:
Exactly, and that's why in React Native, the JavaScript thread is a separate thread. We don't run all of the JavaScript on the UI thread. However, whenever you have stuff going back and forth between those two threads, there's a little bit of an overhead there. And you also can't do any UI stuff on non UI threads. So you can't actually go in there and be like, draw this thing or move this thing or whatever. You have to do that on the UI thread, so you want to keep all of the other work off of it. But if it is UI related, it needs to happen on the UI thread and that's going to be the fastest, and that's totally what an animation is. Good. So it's a UI thing, and so you need to run that on the UI thread so the Lin or objective C is going to be running on the main thread. It's going to be executing all of the different steps over time that it needs to essentially every frame to move elements or animate properties of elements and things like that over time so that you see that animation happening. Also handling touches and sending those events back to the JavaScript thread and over the bridge, or if you're in bridge list mode directly to the JavaScript site so that you can then take those things and do things with them.
Robin Heinze:
It works so much better than trying to do it all in the JS thread. What happens if you want to defer something to wait until all the animations are done?
Jamon Holmgren:
Yeah, this happens. Sometimes you have an animation that happens and then you want like, Hey, I want to know when all animations anywhere in the app are done. Then I have this long running process that I need to have happen. That would be really noticeable to the user. If you started it during animations, everything would start stuttering. It would be a little more laggy. Maybe the user is in the middle of moving something with their finger or something, and so there is an interaction manager run after interactions thing that you should probably be using for almost everything that you can kind of delay a bit. So a good example of this would be metrics. Like if you collected a bunch of metrics and you want to send it off to the server, that doesn't need to go away right away. You can actually wait a little bit, do this, run after interactions, and then kick off a ping over to the server if you're doing some sort of calculations. If you're loading something, caching something that isn't immediate, doesn't need to happen immediately, just do this and then it'll wait until everything's done and then okay, we have a little bit of time where there's a little bit of a gap here. Let's send this off.
Robin Heinze:
This can be a good tool to reach for if you're trying to improve your app's startup time or just performance in general. If there's a screen that's taking a long time to load this as a tool you can reach for.
Jamon Holmgren:
And really, I think it's designed in particular for when the user is noticing the performance stutters because of animations and interactions. So you see stutters and stuff, throw some figure out what would be running at that time. That's kind of taking more time. Maybe even things like, I don't know, like hydrating your state model or something like that. Something like that could be a longer running synchronous task or something like that. So definitely reach for this interaction manager run after interactions. That's a little bonus r and r explains there, but that's essentially what use Native Driver does. Of course, reanimated does a lot of stuff and actually Shov from Software Mansion was I believe the initial person to work on the animated use, native driver implementation, and then he took that back to Software Mansion and created Reanimated,
Robin Heinze:
Which runs animations on the native.
Jamon Holmgren:
It does, yeah. I don't even think they have a
Robin Heinze:
JavaScript. It's just straight up. That's what it does. Neither. You don't have to specify any option, but unless your animations are pretty simple, you're going to have a better time using reanimated simply just because the API is, there's a lot of developer experience goodies like hooks and the API is really easy to use and has a lot more features than the default animated API. So I really enjoyed using reanimated.
Jamon Holmgren:
We did talk with Shov in React Native Radio 2 36. The title is Reanimated two, but Reanimated three actually was coming out pretty soon afterward. And so we talk about Reanimated three as well in there. And I think they're working on four now, or is four
Robin Heinze:
Out? Four is, I don't believe four is out.
Jamon Holmgren:
Four is not out yet. Okay. Okay. Believe it or not, I think we're actually pretty much done with this, and this is what we're looking to try to do with RR Explains is do some deep dives into very specific things. This is a very specific thing. We could have done the whole animated API,
Robin Heinze:
Right? Right. That would've like turned it from a 20 minute episode to a two hour episode.
Jamon Holmgren:
That's true. Yeah. It would've just kept going and going, so I think we'll leave it at that. If you have something that you want us to dig into, just something you've never like you use all the time, but you don't really know how it works, let us know. RN Radio at Infinite Red and we will be happy to take a look at it and see if it's something we want to do in a future. Anar explains. If you want to nerd out more about this, join our Slack community community, infinite Red. We have well over 2000 React native developers in there. And you can also find me on Twitter at jamon hol. You can find Robin at Robin Heinz with an E, and you can find React Native Radio at React native r dio. Thanks everybody, and we'll see you Allall next time. Bye.
Jed Bartausky:
As always, thanks to our editor, Todd Werth, our assistant editor, Jed Bartausky, our marketing and episode release coordinator, Justin Huskey and our guest coordinator, Mazen Chami. Our producers and hosts are Jamon Holmgren, Robin Hines and Mazen Chami. Thanks to our sponsor, infinite Red. Check us out at infinite.red/radio. A special thanks to all of you listening today. Make sure to subscribe to React Native Radio on all the major podcasting platforms.
There’s no perfect time to get started. Whether you have a formal proposal or a few napkin sketches, we’re always happy to chat about your project at any stage of the process.
Schedule a call