React Native Radio

RNR 218 - Performance Enhancing Drugs for your React Native app with Mark Rickert Part 2

Episode Summary

In the second of this two-part series, Mark Rickert joins the podcast to talk about performance-tuning your React Native apps.

Episode Notes

In the second of this two-part series, Mark Rickert joins the podcast to talk about performance-tuning your React Native apps.

 

This episode 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.

Helpful Links:

  1. useMemo & useCallback
  2. Use React Memo Wisely
  3. Don’t overuse React useCallback
  4. requestAnimationFrame
  5. Redux Performance tips
  6. InteractionManager
  7. TurboModules and Fabric
  8. React State Museum

Connect With Us!

Episode Transcription

Todd Werth:

Welcome back to React Native Radio Podcast. Brought to you by that company you love, reminding you that they will be bought by a company you'll hate soon. Episode 218, part two of performance-enhancing drugs for your React Native app.

 

Jamon Holmgren:

So we have to talk a little bit about the title. I didn't actually talk about the title last time, not that much, it's called performance-enhancing drugs for React Native app. Why are we calling it that? I mean, you're not actually taking drugs?

 

Mark Rickert:

No.

 

Jamon Holmgren:

Mark, you're not actually on drugs right now.

 

Mark Rickert:

Absolutely not. I only take performance decreasing drugs.

 

Jamon Holmgren:

No performance enhancing drugs. Fair enough, fair enough. I'm going to actually just get right into this though, this is part two, if you haven't listened to part one, go back and listen to part one that would be React Native Radio 217. And this is part two of that series and we are going to be talking about a whole bunch of more performance enhancing tips for your react native app. Of course, we're not going to be able to get to everything, there's a lot of different ideas on how you can approach performance. And it's almost like its own discipline in and of itself, but we're going to do our best to give you some ideas.

 

Jamon Holmgren:

Of course, I'm Jamon Holmgren, your host. I am the CTO and co-founder of Infinite Red. And today I'm joined by my great co-host Mazen, who is back in the saddle after missing the last episode. How's it going Mazen?

 

Mazen Chami:

It's going well.

 

Jamon Holmgren:

Mazen lives in Durham, North Carolina, former pro soccer player and coach, and is a senior React Native engineer who works here at Infinite Red. Jon Major isn't here. And of course, Robin is still on her maternity leave. I actually messaged Robin the other day and said that, "We're doing just fine without you in fact-

 

Mazen Chami:

Oh no.

 

Jamon Holmgren:

... The podcast is awesome." No, I didn't say that.

 

Mazen Chami:

Yeah. She's not going to want to come back.

 

Jamon Holmgren:

I know, right? I said we missed her and of course it'd be nice to have her back, but it's great that she is getting some time off to spend with her new little one. So, we also have just like last time, our guest host, Mark Rickert, who is a principal software engineer here at Infinite Red. Mark and I have known each other for many years now, I can say that I think.

 

Mark Rickert:

Yeah.

 

Jamon Holmgren:

How many years? It's like eight years.

 

Mark Rickert:

Probably a decade by now.

 

Jamon Holmgren:

It's close to that, yeah. And he lives in North Carolina as well, Asheville, North Carolina and he works here at Infinite Red with us. And of course, as we mentioned in the last episode, you are moving to Utah though.

 

Mark Rickert:

Oh yeah, going back home.

 

Mazen Chami:

No longer a Carolinian, but now a Ute.

 

Mark Rickert:

A Ute.

 

Jamon Holmgren:

This episode is sponsored by infinite red. Infinite Red is a premier React Native design and development agency located fully remote in the US and Canada. If you're looking for React Native expertise for your next React Native project, hit us up. You can learn more on our website, infinite.red/reactnative and don't forget to mention that you heard about us through the React Native Radio podcast.

 

Jamon Holmgren:

And also if you're a senior level React Native engineer located in the US or Canada and interested in working with this amazing team, go to careers.infinite.red and fill out the form.

 

Jamon Holmgren:

All right, let's get into our topic for today. Performance enhancing drugs for your react native app. And I think and this is part two and what we're going to focus on is a little more the JavaScript layer and sort of the react part of React Native. So let's start with hooks. How do you optimize hooks?

 

Mark Rickert:

Yeah. Hooks were introduced a few years ago and a lot of people seemed to have struggles figuring out how the hooks actually work and when converting their regular class components over to the new functional components that react is going towards. And there's a few really commonly used hooks that react provides to us that we just need to watch out for that those are use effect, use memo and use callback.

 

Mark Rickert:

And I'm just going to go through here real quick and explain what each one of those does. The use effect is basically a way to make some bit of code run every time a value changes. So maybe you're watching an ID of something and want to change something on your screen every time that changes. So you'd put that code inside a use effect and give that ID as a dependency and that code block would run every single time that that ID changes.

 

Mark Rickert:

Now, use-memo is kind of a way to memorize the value of a function. And so if you have something that you need to compute that takes a while and doesn't need to change very often. You should wrap it in a use memo so that you really only recalculate and change that when you need to. And then use callback is similar to use memo, except it's basically a function generator that regenerates the function every single time, one of those dependencies changes so that you can call it and it will have all the updated values.

 

Mark Rickert:

And so a lot of people don't quite grok the difference there between use memo and use callback. And there's some really great articles that will put in the show notes, one of them is by Kent C. Dodds, an icon in the software development community. And he talks about use memo and use callback and how they can be dangerous at times by using them too much, by re-rendering when things don't need to, because I don't know if you guys know this or not, you probably do, but the react effects, they actually do a shallow comparison. So if the dependency changes and it's a deeply nested thing that changed, react isn't really going to even see that change, it's just going to re-render the function no matter what, it's not going to tell you that, "Oh, I didn't need to Re-render."

 

Mark Rickert:

And then there's another couple of articles we're going to link by a guy named Dmitri Pavlutin. And he has some articles basically about when you should and shouldn't use use memo and use call backs. I think they're actually really overused, I prefer the reacting to state versus reacting to other things. So I tried and shove as many things into my state models as possible and just observe them.

 

Jamon Holmgren:

Of course we use MobX-state-tree and MobX React, so that kind of gives us a little bit of a leg up on the observability side of things, but absolutely that's true. And I think that we've seen this in a couple of our more recent projects where the teams that we're working with great teams, but they tend to maybe I would say overuse some of those things without necessarily measuring, is this helping or not? It's just sort of like by [inaudible 00:07:17] and that's something we've had to sort of advocate for.

 

Mark Rickert:

Exactly.

 

Jamon Holmgren:

Only use it when you are noticing that this is a problem.

 

Mark Rickert:

Right. And react is so fast, a lot of times it can re-render that function that you're using a use callback or that value that you are using for use memo without any real speed decreases, especially if it's a really teeny, a tiny function. These effects, the use memo and use callback should really only be used as a performance enhancement and not the default, so just don't memorize and call back everything in your function unless there's actually a good reason to do it.

 

Mazen Chami:

Yeah, Mark, we were talking about this before, in use effect there's sometimes when putting guards around your set states would come in handy because you don't want to create another re-render.

 

Mark Rickert:

Yeah, exactly. When you call set state inside of a use effect, it actually re-renders the component twice. Once for the use effect and then once when it sets state in the use effect, so it's going to re-render that twice. And an easy way that you can prevent that second re-render is by just putting a guard around your set state function so that you check to see if it actually needs to be changed or not. And that can actually vastly decrease the number of renders inside of your components, especially if they're large. So I try and put a guard in front of my set state function calls by default. I wish react would do that by default though.

 

Mazen Chami:

Another point with use effect is most people don't realize at the end of your use effect, you can usually return a callback and that callback usually clears any timers or listeners that you have. And also could unsubscribe you from whatever it is that you're doing, so simple library like Lottie for your animations, when you want to clear or reset your animation so that when you unmount everything kind of gets reset and put back to the original state. And this is probably especially true when it comes to timers specifically.

 

Mark Rickert:

Yeah, definitely timers. I've run into situations where I had a set timeout inside of a use effect, but it was creating a memory leak, because it was calling a set state function in that timeout after the screen was already pushed off the stack. So the use effect, when you give it a return statement at the very end, that return call back actually fires when the component unmounts.

 

Mark Rickert:

And so you should do all of your cleanup of whatever you're doing in that use effect inside that return statement. And that goes for event listeners, timers, anything you're subscribing to that needs to be unsubscribed to when your component unmounts should be done in that use effect return callback.

 

Jamon Holmgren:

One thing I like to also watch for is when you have maybe a complex screen or component or something that is doing a lot, anything that changes a lot should really be kind of encapsulated in its own component, even if it feels a little awkward to do that, even if you're like, well, okay, this could really just be dropped right into the main component. But if you put it into a child component, then you can control its re-renders in a more targeted way. If you had a timer that was updating every second or even every millisecond or something like that.

 

Jamon Holmgren:

Put that into its own component so it's not re-rendering the whole parent, it's only re-rendering itself every millisecond or whatever. And you're just sort of isolating the pieces that are changing a lot and telling them, Hey, you can re-render a lot, the parent is just going to kind of like sit there and let you do your thing.

 

Mark Rickert:

Yeah. I think the goal here with what you're talking about is to get as few things to re-render per render cycle as possible. And only the things that actually need to change.

 

Jamon Holmgren:

And I think that dovetails well into talking about the state management side of things, so I'm going to start with MobX-state-tree, our favorite state management library and I'm primary maintainer of. And we also use MobX-react-lite, which is the library that connects it to React. One of the things that MobX-state-tree and MobX-react-lite do really well is you can do targeted re-render. So if anything changes as mark mentioned earlier, like a deep property somewhere deep in your state tree changes, only the components that are observing that property will change or will re-render.

 

Jamon Holmgren:

So you can start with, okay, I have this timer and in state I'm changing this timer, I don't know, you wouldn't do it this way, but let's say that you had a timer property and you were just changing that all the time. You could have that deep child component and I like to call this free range parenting for components, so let your children go and do their thing and let them kind of be smart, don't try to over control them, don't be a helicopter parent here where you're just constantly hovering over them and saying, oh, you need to change, you need to change, you need to change. Because what that does is that makes the parent re-render all the time.

 

Jamon Holmgren:

When the child has the ability to understand when it needs to re-render by using something like MobX-state-tree and MobX-react-lite, then it can continue to re-render that way. MobX-state-tree performance is a huge topic, we can maybe dip into this a little bit, but I would say in general, using MobX-state-tree is going to be performant just right out of the box.

 

Mark Rickert:

So Jamon, have you taught your children how to cook dinner for you so you don't have to spend the time re-rendering dinner?

 

Jamon Holmgren:

That's a great idea, I'm going to do that after this.

 

Mark Rickert:

Parenting tips on React Native Radio. First, we had news and now we've got parenting.

 

Mazen Chami:

Cover all topics.

 

Jamon Holmgren:

I feel like I've been a parent for 16, almost 17 years and the further I go into it the less I know.

 

Mark Rickert:

I know a lot of our listeners probably use the Redux in their apps. And Redux is kind of more of a state design system instead of a state management tool, I was wondering if one of you guys could talk about Redux. I haven't used Redux in a little while, but I do know that there is an actual page on their docs for performance enhancements for Redux. And again, you should always read the docs for whatever you're working with, if you haven't read the docs and don't know how something works, you should definitely take the time to go and read about it.

 

Mazen Chami:

Totally agree with you on that Mark. This page for performance, which will link in the show notes does a good job of kind of encapsulating everything to help you kind of understand where you can improve your performance. In a quick glance at this document, you might notice that it's very similar to their, how to get started with Redux. So they're not doing anything special when it comes to improving performance specifically, all it is is just kind of reinforcing the fundamentals of Redux and Redux toolkit if you use that in all that. So, something like combined reducers that kind of puts all your reducers in one, rather than having to call each one individually, that can be very taxing on your app. So and again, looking at the documentation for getting started, that's like their default in how to set up your reducer.

 

Mazen Chami:

And then one other thing that sometimes we end up doing is we dispatch a bunch of calls, whether they're API or Redux specific back to back. So we'll have dispatch A, dispatch B, dispatch C when instead Redux gives you the ability to batch those. And that's also a way where you can kind of improve it rather than waiting and then keeping a loading state while you're doing all ... Waiting for all that to happen.

 

Mazen Chami:

So yes, read the documentation, because the documentation doesn't really have anything crazy in there, it's just basically follow the basics of it and that'll kind of get you a heads up and forward in the game of performance in this case.

 

Jamon Holmgren:

Yeah. And it's worth noting Mazen, even though we love MobX-state-tree at Infinite Red, Mazen is currently working on a Redux project, pretty big Redux project for us. And so we've done a lot of Redux over the years and we'll continue to do a lot of Redux over the years. And yeah. I mean, I think the big thing with Redux is it's important to really try to have a mental model of what your state is doing, where your data is and when you fire off an action to a reducer, you know what's happening, what's changing and reduce it. There's this idea basically of, you're not going to increase the clock speed with a programming language, what you're going to do is you're going to try to do less and that makes it faster.

 

Jamon Holmgren:

So anything, all the way down the stack from the CPU itself is doing less all the way up to the most high level languages and even just how you use an app, you try to do less and it will be faster. And so again, this is a situation where sometimes cashing some things is a good idea if it's heavy re-computations, but think about how you're really structuring your data model.

 

Mazen Chami:

One thing I've also noticed in working with Redux a lot recently is, some people will usually have set state handle their fetching state essentially. And I've also noticed that offsetting that to Redux is a little bit more performant and easier instead of having to listen to, put an effect on your state and then we talked about it earlier and resetting it once it's done. The nice thing about offsetting that to Redux is Redux and Redux toolkit have this state when you dispatch something of dot pending versus dot fulfilled and dot error. So that's a really good scenario where you can dot pending is fetching true. And then you're automatic, because it's a hook, the use selector is a hook, show you your loading page and then when it's done, you set it to false and then your data will automatically be available for you at that time.

 

Mazen Chami:

I've noticed that to be faster in the react app rather than using the state and then waiting for the data to come back and then populating it. Less render ... You do have the render when it changes, but it's much more performant doing it, having your state management tool offset that workload.

 

Jamon Holmgren:

Yeah, that's a great point Mazen and there are a lot of articles about Redux performance out there, so you can certainly do some more kind of Googling around that, but it's possible to write, perform it, Redux apps, it's very possible to write performat MobX-state-tree apps. There is one thing and I'd be remiss if I don't mention this about MobX-state-tree. If you run into a situation where you have a ton of elements, all re-rendering very, very quickly on a screen, you can sometimes run into a situation where MobX-state-tree bogs down a bit. It's something I've noticed.

 

Jamon Holmgren:

Now, you have to have a lot, by default I think MST is just performant right out of the box, you're just not going to notice issues. And in fact it's I think easier to keep it performant throughout an app. But if you have a very large screen with a lot going on, probably it happens a little more on web where you might have a big dashboard or something like that, less so on React Native, but you can run into those situations, there are ways around it, sometimes you can't use the exact same tool for everything. And so you just have to look at and say, okay, we're not getting the performance we need here, let's switch to a different tool.

 

Jamon Holmgren:

But yeah, definitely a lot of articles out there about Redux. So context is another thing and a lot of people will use context to kind of distribute state around their app. I think this is probably a little more of a two edged sword here, you can certainly use it effectively, but as my friend Jani Evakallio said once, if you use context and don't really think about how your data model is structured, you're going to end up with a worse version of Redux. That's essentially what you're going to do. And so you do need to be thinking in terms of ... I guess if you're using context it may seem simpler, but you also are opening up a lot of footguns.

 

Mazen Chami:

I also feel like if you are going to go with context over MobX-state-tree or Redux, you do miss the fundamentals that those management tools kind of set up for you. And instead you kind of have to set it up from scratch now. Maybe you have a specific data structure where you need to use context, although I would probably challenge you and say, take a look at Redux and MobX-state-tree a little bit more, because maybe you could have offset that to them, instead to kind of building your own concept out of the box.

 

Jamon Holmgren:

It is also worth noting that there are many other state management systems out there, I'd like to link to in the show notes, Gant Laborde's react state museum, which he calls a whirlwind tour of React State management systems by example. So there's all these different examples of writing the same thing in different React focused state management systems. And you can definitely check that out, there's all kinds of cool stuff. And some of them will be faster by default than both Redux and MobX-state-tree. Some of them more optimized for those things, of course, with state management, you're always looking for the right, I guess, balance between developer experience and performance and just features overall.

 

Mark Rickert:

So let's move on from talking about optimizing state management and let's talk about blocking the main thread. Sometimes when we're doing some heavy computational things in JavaScript, we can block the main thread and that even if it's just a few milliseconds react actually gives us some really great ways to make the app feel like it's not blocked. And those two tools are request animation frame and interaction manager.

 

Jamon Holmgren:

Yeah. And they're subtly different, so request animation frame is really designed, it's actually a function on the window object and it's designed to allow you to handle animations. So you'll get the next animation frame that's coming through and be able to do something every animation frame. And you usually would call the next request animation frame from your request animation frame, it's kind of a recursive thing.

 

Mark Rickert:

Yeah, request animation frame is more for continuous animation and changing that over time, where the React Native interaction manager comes into play is when you want to run all of your animations and then do some heavy computational function. So essentially what you would do is wrap what you're trying to do inside of the interaction manager. And it will make sure that your screen responds to, let's say a button press.

 

Mark Rickert:

So if you've ever had an experience where you press a button and it stays pressed until the thing it's doing is over with, you've run into this issue. Essentially, if you wrap it in an interaction manager, it allows the button to press and UN-press so that it appears to the user as though their button press was successful. And then does the thing that blocks the main thread for a few hundred milliseconds or whatever. So it's just a way to help make your apps feel a lot nicer to users instead of having everything feel very slow when you press buttons or [pressibles 00:23:22] or something like that.

 

Jamon Holmgren:

That's a great explanation of those two functions. And I think it's something that's probably underutilized in apps, so something that you definitely want to look into. We'll link into, we're going to have a lot of links in the show notes, but we'll link to that in the show notes as well.

 

Mazen Chami:

Building on our concept of reading the docs, Mark, I'd like to get your take on using lists in general. So whether it's section list flat lists or virtualized lists, because I feel like that can sometimes bog down your app a lot.

 

Mark Rickert:

Oh yeah definitely. Virtualized lists have kind of been an issue since the beginning of React Native, just because we're trying to render native cell views inside of a native list view in React Native. And having a lot of re-renders can really slow that down. And again, with reading the docs, React Native has a really great page on how to optimize your flat list configuration and that applies to section list or if you are using virtualized list directly. But I think the biggest thing to take away with creating performant virtualized lists is to make sure that you're using lightweight components wherever possible, the heavier your component is the longer it takes to render the less performant your list is going to be because that list is rendering that same component over and over and over and over again, to display it on your screen when you're scrolling up and down.

 

Mark Rickert:

So having a performant very lightweight component in your render function for your virtualized list is going to help with the scroll stuttering and sometimes you you'll see where there's a white space where it hasn't painted the render yet while you're scrolling up and down. So definitely lightweight components are the key to making virtualized lists performant.

 

Mazen Chami:

And then building on that too, if you have larger components, make sure to memorize them or even callback, use callback to help it render easier.

 

Mark Rickert:

Yeah, definitely. Sometimes when you're trying to optimize performance and using the react dev tools, you'll see a bunch of anonymous functions all over the place and it makes it really hard to debug, so if you move your fat arrow anonymous functions out to named functions inside your component, it's going to tell you a lot more about your render process in the dev tools and you'll be able to kind of figure out what's actually slowing down the list a lot easier.

 

Mark Rickert:

And then there's also the GIT item layout property for the lists, now virtualized lists and react native calculate the view size on the fly. And so if you can give it the view size and it doesn't have to calculate it, that's going to make your list a lot more performant, it's not always viable to do that, say if you have different types of list component items in the virtualized list, but if you're just displaying a list of items that all have the same row height, you can specify that in your GIT item layout and that will vastly improve the performance and speed of scrolling for your flat list or section list.

 

Jamon Holmgren:

Yeah, I remember this was a thing when I was doing native coding with UI table view, you remember that Mark? Where you would have to kind of calculate the image size and often we were rendering a cell twice, because we would render it once to measure its height and then we'd render it again to actually shove it into the view, which was a waste of course, but if you-

 

Mark Rickert:

Less than ideal.

 

Jamon Holmgren:

Right. But if you could either be like, okay, well, based on these properties, I think it's about this size or just have a fixed size, then that really made sense. Maybe you'd have cells that would either have an image or not and if they had an image, they would be taller and you could say, oh, this one has an image, so it's going to be of the taller size. It doesn't have the image, so it's going to be smaller. It's just a hint for the layout engine to kind of drop it in there, a placeholder and then it'll resize it once it actually gets the view of course.

 

Mark Rickert:

Yeah, definitely. So just to wrap up this section, flat list, section list and or if you're using virtualized list directly, that they really are where you can make a lot of inroads into performance in your React Native application, because they're most often the source of performance issues.

 

Jamon Holmgren:

It would not surprise me if we had a new replacement for flat list in the next year. And the reason for that is the newer architecture coming where we can and do direct synchronous fast communication, not using the bridge. We won't necessarily go into that right now, because that's just speculation, but it wouldn't surprise me at all if we ended up with a replacement for flat list that's much more performant.

 

Mark Rickert:

That would be awesome.

 

Mazen Chami:

Building on that Mark, let's talk about some of the most commonly used modules and some issues you might have run into in the past. React Native WebView.

 

Mark Rickert:

Yeah, so a lot of people use React Native WebView and I think Jamon is the maintainer of this project as well, our core maintainer.

 

Mazen Chami:

Can the editors cut that out please? I don't want to ... Sorry for bringing it up as an [crosstalk 00:28:42]-

 

Mark Rickert:

Sorry, I know it's a little bit of a sore spot, but this was originally pulled out of React Native and-

 

Mazen Chami:

It was, I was the one who did it.

 

Mark Rickert:

Yeah, and then they made it a community module because React Native was slimming their entire API and this just seems like-

 

Jamon Holmgren:

Like part of the lean core initiative, yeah.

 

Mark Rickert:

Exactly. This seemed like something that could just be pulled out. But yeah, it does have rendering issues, the initial render startup time of React Native WebView is quite heavy, takes a pretty long time to paint to the screen. And so I have a rule that I just don't ever use it unless it's a full screen web browser. Like I've seen in the past where people have used React Native WebView to just render some static HTML or they pull some HTML from their server and want to display it in the app. And I think that something like React Native render HTML would be a lot better way to do that, where it just kind of converts your HTML into react components and displays them, instead of trying to load up the entire react native web view component, which again takes a while to start up.

 

Mazen Chami:

React Native Maps, how about that? I haven't used that in the past before.

 

Mark Rickert:

Oh yeah, React Native Maps is a really big and widely used library and I've used it extensively and I've run into some performance issues with rendering things inside the map view like markers and polylines and shapes and stuff like that. You just have to make sure that every single child of map view has its own unique key, because when the map view goes to add and remove things from itself, or if you're adding and removing them via your JSX, sometimes if they don't have a key, especially on Android, you'll just get a red screen and it'll say it can't figure out which view to select and remove.

 

Mark Rickert:

So sure that every child has its own unique key. And then another kind of got you surrounding map markers, there's a property on there called tracks view changes and if it's defaulted to true. And if you have it set to true, it re-renders on every render.

 

Mark Rickert:

So you need to take that and set it to false if you're going to render it once and nothing ever changes, but say you have an image in your map marker, you would have to have that be in tracks view changes equal true, until that image either loads or fails to load. And then once that's done, then you can set it back to tracks view changes false. So that that item won't re-render ever again even if it's parent re-renders. So those are kind of a few got yous that I've found in React Native maps.

 

Mazen Chami:

That's a good tip, yeah. The next one I want to talk about is react navigation, this one I'd say is a big one because if a user is trying to move from page to page and there's a glitch or it's slowly swiping in, I feel like this is a poor experience that having the best performance on it would be ideal on any application.

 

Mark Rickert:

Yeah, definitely. And react navigation, it's a pretty widely used navigation library and I think people like it because it offsets a lot of the functionality to native, it creates native screen instances, it uses native header bar layouts and stuff like that. And a lot of times you want to change those items inside your react screen component, and you can always call navigation.setOptions and update things on the fly. You should always put your title and what buttons configurations you have for a screen inside the navigators stack, but sometimes that's not an option.

 

Mark Rickert:

So you need to do it from a screen after, I don't know, computing some property whether or not to show a button.

 

Mazen Chami:

Getting the title back from an API for example.

 

Mark Rickert:

Exactly. And sometimes we know that right away. And one got you that I found is that if you're setting your options for react navigation inside of a use effect, that actually gets run after the first loop of the component render. So you could have a situation where your screen pushes onto the stack, renders your screen and then the title bar just pops into place. And so that always just looks odd. And I think that performance enhancements also mean making it look better and more performance to the user. And so if you just move the navigation.setoptions out of your use effect and put it inside of a used layout effect, it will actually set and render at the same time as your first paint, so that the title bar and the title are already there and don't snap into place or show and hide in the middle of a popping onto the screen or navigating onto the screen.

 

Mazen Chami:

Yeah, that's good to know. Again, something else that we'll link in the show notes, Kent C. Dodds also has an article about use effect versus use layout effect that Mark was just talking about that you can read a little deeper into.

 

Mark Rickert:

Yeah, I think the basic gist of it is that use effect runs asynchronously after the first render and use layout effect runs synchronously with the first render.

 

Jamon Holmgren:

Perfect, well, I want to move on to another topic here, which is, how will the new architecture affect performance? I already mentioned that there's a potential new flat list alternative that I saw in a recent Reddit AMA that's definitely on the table, the Reddit AMA with the core team.

 

Mark Rickert:

Yeah, I saw that and I was really excited when I saw that there might be a flat list alternative coming.

 

Jamon Holmgren:

Exactly, because that is a pain point. Also, I think the JSI in turbo modules and stuff should eliminate a lot of ... And I guess just the direct communication, skipping the bridge will eliminate a lot of the JavaScript native communication bottlenecks. So there's a lot of those things where we're trying to communicate back and forth over the bridge and it's asynchronous and slow. So moving towards synchronous communication, just calling functions basically directly across this interface I think is going to be good.

 

Jamon Holmgren:

Unfortunately, I don't think we know a lot yet just because there hasn't been a lot released about it to be honest. We are planning to hopefully have a Facebook engineer on soon to talk about the new architecture, so look forward to that, I'm working on that. And potentially really improve the ... Maybe this is the silver bullet that will improve performance.

 

Mark Rickert:

Maybe, we'll see.

 

Jamon Holmgren:

We have one last question on the docket here and Mark and I disagree about this one. So we're going to have an argument.

 

Mark Rickert:

Oh, oh.

 

Mazen Chami:

I'm going to go grab my popcorn, hold up.

 

Jamon Holmgren:

When should you drop into native to get native looking performance?

 

Mark Rickert:

So, in my opinion, I think you should avoid native at all costs if you can. The JavaScript native bridge is slow, it only transfers strings that it serializes back and forth. And so if you're trying to get data from native, I don't think you should go to native as your first choice. And mainly for me, because you have to write it twice. Once in swift and objective seal and once in Kotlin or Java. And so you're creating more than double the work for yourself than if you just figured out how to do it on the JavaScript layer.

 

Jamon Holmgren:

So I actually don't disagree with Mark in that sense at all really. I think that those are great reasons to avoid native quite a bit. But I do think that it is a viable option for when you can't achieve or it's very difficult to achieve the performance that you're looking for on the JavaScript side, you do want to avoid the bridge for sure. Now eventually with the new architecture we can do things more synchronously, but let's say that you can't and you're just using the bridge.

 

Jamon Holmgren:

One thing that I think is cool is that you can trigger native things without ever going across the bridge. So the other day on a react native live on my Twitch channel, I was basically live coding a native component. And what I did was I intercepted a click on the element and then I triggered an animation and I didn't tell JavaScript at all that this was happening, it just all happened in the native side. Just everything, all the interactions and everything were happening on the native side.

 

Jamon Holmgren:

When I eventually told the JavaScript layer was something that it needed to know, Hey, there's something that has happened that you need to know about. But otherwise it was just handling it itself. So I think if you can do that and a lot of times that's more like animations or whatever, maybe even maps is a good example, I think a really good example of this would be a super thin specialized web view. Let's say and you're right Mark, you shouldn't use React Native WebView which is way too heavy for that, it's a general purpose tool, it has a vast API surface.

 

Mark Rickert:

Everything to all people.

 

Jamon Holmgren:

Everything to all people, which is nice when you just need to get a web view up, right? It's like the DX is pretty decent.

 

Mark Rickert:

Yeah, it's great for making an internal browser in your app, it's really good for that.

 

Jamon Holmgren:

Right, exactly. It's got all those things. But if you just ... And there are some situations where you just need to inject a small web view into an app and maybe the react native render HTML doesn't quite work for what you're trying to do. If that's the case, then you can drop in a native, you can write a very, very thin wrapper around the native web view and then drop that in and then only communicate back to the JavaScript side once there's something to report if at all. Sometimes there's not even that, it's just a display only thing.

 

Jamon Holmgren:

So I think there are situations where dropping into native makes sense and I like to have the tools in my toolbox to not be scared of that. Now, I know that Mark you aren't scared of it whatsoever, you are a native developer for many years.

 

Mark Rickert:

Yeah, I was a native developer before React Native even came out, so I've been doing this for years.

 

Jamon Holmgren:

Exactly. You know the iOS and Android side like the back of your hand, and you can do that stuff, no problem. But with that said, I do actually agree with you that if you can do it in the JavaScript side and achieve the performance you need and whatnot, then you only have to write it once.

 

Mark Rickert:

Yeah, I think as we wrap this episode up it's important to reiterate that performance shouldn't be an afterthought, but it also shouldn't be the first thing you do. You should iterate on performance, you should write your things so it works and then make it performant, because pre-optimization again is the root of all evil, pre-optimization of things can lead to lots of problems down the road. So just use the performance tools, make sure you know how to use the flame graph and figure out how fast your components are rendering, so that you can optimize on a targeted level instead of just trying to do an across the board indiscriminate optimization.

 

Jamon Holmgren:

Yeah, Kent Beck said, make it work, make it right, make it fast. In that order.

 

Mark Rickert:

In that order, exactly.

 

Jamon Holmgren:

Very cool. Thanks so much for all of the insight that you both have dropped on this episode. Where can people find you online Mark?

 

Mark Rickert:

Yeah. I'm @MarkRickerd on GitHub and on Instagram.

 

Jamon Holmgren:

Perfect. And Mazen?

 

Mazen Chami:

I'm @MazenChami.

 

Jamon Holmgren:

And you can find me @JamonHolmgren. you can also find React Native Radio on Twitter @reactnative R-D-I-O. Thanks of course to Mark Rickert for joining us and dropping knowledge on this episode and part one as well. As always thanks to our producer and editor, Todd Worth, our assistant editor and episode release coordinator, Jed Bartausky, our social media coordinator, Missy Warren, and our designer, Justin Husky. Thanks to our sponsor, Infinite Red. Check us out at infinite.red/reactnative. Special thanks to all of you listening today. Make sure to subscribe on all the major podcasting platforms. You can just find us as React Native radio and reminder that Infinite Red is hiring reactive engineers, if you're a senior level reactive engineer located in the US or Canada, go to careers.infinite.red. Fill out the form and we'll get in touch with you. So thanks a bunch. See you next time.