React Native Radio

RNR 293 - Real Life React Native With Benji Lightstone

Episode Summary

This week, Jamon is joined by Benji Lightstone, a senior software engineer at Spatial. They talk about Benji’s journey into software development and how they use React Native at Spatial.

Episode Notes

This week, Jamon is joined by Benji Lightstone, a senior software engineer at Spatial. They talk about Benji’s journey into software development and how they use React Native at Spatial.

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.

Episode Links

  1. https://www.spatial.io/
  2. React Native Unity View
  3. React Native Video 

Connect With Us!

Episode Transcription

Jamon Holmgren:

Hey everybody, I'm Jamon and this is our series on React native radio that we call Real Life React Native. This is a series where we interview software developers who work on real life react native apps. These are supposed to be quick and more rapid fire and fun. So let's just get started. I'm sitting now today with Benji Lightstone. Benji is a senior software engineer at Spatial. He lives in the Toronto area in Canada, and he told me that he started his career in corporate sales and decided at one point to try software development and apparently really loves it. So that's pretty cool. Now, spatial is a very interesting app. I can't wait to get into this. Thanks for coming on, Benji. Really appreciate it.

Benji Lightstone:

Yeah, thanks for having me. Jamon listened to a couple of handful of your episodes and excited to be here.

Jamon Holmgren:

Yeah, fantastic. I always love these series because we actually get to talk to people who are not just theoretically building something on the side or whatever, they're actually shipping to real users and I can't wait to hear about this. So let's get into this. What is the elevator pitch for spatial?

Benji Lightstone:

So there's two elevator pitches for spatial, one for players and one for game developers. So the one for players is you can come and play some of the most beautiful games on any device that you have for free that are published on spat shuttle. So if you have a computer or if you have a mobile phone or if you have vr, it doesn't matter what device you can come play and they're all free. And then for developers, the pitch is you can build within Unity. So Unity is one of the most common game engines. So if you already build within Unity, you can easily publish games on spatial and you can actually build on top of a lot of things that we provide you. So we provide avatars from a company called Ready Player Me. They're pretty big in that space. You get multiplayer, you get in game like text chat and voice chat. You can sell items and you can actually use C scripting as well. So it's a pretty powerful way to be able to publish games and think about it a little bit like Expo helps simplify React native for you in a way you can think about spatial a little bit like that, and it obviously helps you reach an audience.

Jamon Holmgren:

That's a great pitch. Yeah, I love the kind of analog to expo because it's really building on top of a core technology and adding a bunch of features that just make the developers' lives easier. Things that they're going to need anyway. They're going to need all this stuff anyway. What parts of spatial are in React native?

Benji Lightstone:

So our mobile app is written in React Native, and the way that it works is we have a Unity app that is shared across all three platforms, mobile, web and vr. And then each of those clients actually uses a React layer on top of it because building Unity UI can get quite tedious. And then so let's say you come to the spatial app and you start browsing around, you log in, make an account, or you start browsing for games. All of that is built in React native. And then once you jump into a game, the actual 3D world that you see is all in Unity, but a lot of the few buttons you'll see overlaid on top of it, like bringing up the in-game chat, for example, editing your avatar. That stuff's built in React native, and if you're a React native engineer, you're like, you'll be able to tell what

Jamon Holmgren:

If I'm getting this right. This is essentially like a Brownfield situation where you have Unity section of the app. You have a React native section of the app where you're mounting React native and using it where appropriate, and then you're communicating back and forth somehow between these different layers.

Benji Lightstone:

So there's an open source package called React native Unity View. So the way it works is React native actually creates the Unity player like Instantiates it and there's React native Unity view. The MPM package has a open message handler, so think about similar bridge similar to the old React native bridge where we'll serialize JSON messages, send it to Unity and as well, that's how it works. And then there's some native plumbing there to make sure that they talk to each other properly.

Jamon Holmgren:

That is fascinating. I love that. I didn't even know that React Native Unity View existed. That's a really cool thing. What about the rest of your architectural stack? What all do you have? Especially in the React native side of things?

Benji Lightstone:

Yeah, so for React native we use, so we're on version 0.71.14, but I think that may, so just for some context for all the React native devs, so you can think about what we might be able to use. So we're still using Flipper for debugging, which is amazing when it works.

Jamon Holmgren:

It is amazing when it works. I love it.

Benji Lightstone:

All the plugins you can have on it are fantastic, but yeah, when it doesn't work, it's not great. We use React Query heavily. We use context for state management. We use sagas, try to avoid use effect as much as we can and do things within our sagas. We use React navigation in some parts of the app, however, it's not exactly designed for what we need to do when you're actually trying to play a game. Those are the major things and React Query has been fantastic. Once we write a feature on web, then you already have a huge headstart just consume that, the query hooks you've made and start building ui.

Jamon Holmgren:

That totally makes sense. Are you using TypeScript or Flow?

Benji Lightstone:

Yes, we're using TypeScript. Yeah. It's such a given to me that I forget about it. Yes, we're definitely using TypeScript.

Jamon Holmgren:

Some listeners are going to be like, why did Jamon mention Flow? But some people do. Oh yeah,

Benji Lightstone:

Yeah, yeah, that's true.

Jamon Holmgren:

This one I'm really interested in because your setup feels not an ordinary setup. How do you handle testing? Do you have automated tests? What level do you go with automated tests?

Benji Lightstone:

We have a QA team.

Jamon Holmgren:

I love it. So

Benji Lightstone:

We don't really do, don't do a whole lot of automated testing. We've explored setting up detox or something else for End-to-end testing. But because we're a startup and we're moving so quickly, it's just not something that we focused on too much. A little bit of unit testing, but that's about it. I think also for us at some point it would be good to add tests, but we might ship a feature and we're testing and experimenting. Is this something that users want to use? And at that point it might not be worth writing the tests.

Jamon Holmgren:

Yeah, that's a good point. It doesn't sound like you necessarily regret. It's more like it's a trade-off decision.

Benji Lightstone:

Yeah, there look, there are probably times when testing would help for some of our key things, but yeah, it's always a balance of time.

Jamon Holmgren:

It is, yeah, absolutely. What about performance? Because obviously the Unity side needs to have a really high performance, but you also need to make sure the React native side isn't slowing things down.

Benji Lightstone:

So we especially need to make sure that React native isn't slowing anything down because Unity is by nature requires a lot of resources.

Jamon Holmgren:

It's going to gobble everything up

Benji Lightstone:

As it should. It's doing a lot of, and if you see some of the games that with the graphics that you can get on spatial running that on, especially what we test on iPhone eights, it's pretty fantastic. We've been able to

Jamon Holmgren:

Get that to work. You go way back there. Yeah,

Benji Lightstone:

We do. Of course, you'll have a much better experience on a newer iPhone. But yeah, I spent about three to five months focusing on performance with another really talented engineer named Jason, and we focused on, so memory, we were getting a lot of out of memory crashes and a lot of that was coming. There was a lot of work we needed to do within Unity, but there was actually a lot of work we had to do within React native as well. So I don't know you guys, if you use React native video much?

Jamon Holmgren:

Yeah, we have a little bit. Yeah.

Benji Lightstone:

It's using Exo player for Android under the hood, which is, I mean I've gotten to know it a little bit, but this guy, one of my coworkers, rock, who's a fantastic Android engineer, not the biggest fan of Exo player, what I mentioned to him, this was causing some problems. He was like, oh no. Yeah, there we were able to save about 300 megabytes of memory just from video because an exo player does some weird things where if you want to loop a video, it has a 52nd buffer by default React native video, and we had four to 10, 12 second videos playing on Loop. It actually fills up the entire 52nd buffer with the video repeated. And these are on a, are you

Jamon Holmgren:

Serious?

Benji Lightstone:

Yeah, it does.

Jamon Holmgren:

So you loop it and it's going to save like 10 copies of it.

Benji Lightstone:

Yeah, that's what I found from some Stack Overflow posts online. I didn't inspect the actual memory allocation, but when I did reduce the buffer size to 12 seconds, I saw a 300 megabyte savings. When I measuring running a memory test to measure it,

Jamon Holmgren:

I'll say this is a good moment to point out to react native developers that often we're quibbling over should you do this JavaScript, use a map or an array or an object or something like that. But often the biggest wins are in things like you said, like video buffers and stuff like that. That's where the most memory is going to be gobbled up. You really need to be measuring these things and actually seeing where's the low hanging fruit rather than trying to chase down a few kilobytes here and there.

Benji Lightstone:

Yeah, I agree. I think it's always good to have big O notation in mind, but I think if big o notation, if you writing something as n squared on the front end is having a big performance problem, you probably have too much data and you need to do something like paginate or something. Right. The bottleneck is before that point.

Jamon Holmgren:

Exactly.

Benji Lightstone:

Yeah. Yeah, exactly.

Jamon Holmgren:

Yeah, that totally makes sense.

Benji Lightstone:

And then, yeah, I can talk a little bit more about some of the other performance optimizations we've had to do because we also had, have you seen Silicon Valley, the TV show?

Jamon Holmgren:

Yes, I have.

Benji Lightstone:

Remember when the phones were heating up and burning everybody?

Jamon Holmgren:

Yes.

Benji Lightstone:

That's obviously a hyperbole and we've never had a phone actually hurt someone, but devices can get quite hot. So we also had to actually reduce the thermal state of our devices because we're trying to do lot on the phone and React native was contributing to that as well. Just because you write some code, ship it quickly, you don't think about how often maybe an on scroll gets called when you scrolling a flat list and then next thing you know every 60 milliseconds you're putting something on the queue and that's just causing the phone to overheat.

Jamon Holmgren:

Yeah, totally. Yeah. I had a discussion online on Twitter the other day. It was actually with the lead of the Hermes team and some other folks, and the question was around do you go performance first or do you do performance afterward? Do kind of a performance pass. Of course, Sten, the Hermes guy, he thinks about performance all the time because that's really, really important to him. And I don't disagree. I think that's important to have in mind. I tend to be a little more balanced. I tend to be like, I can't help but think about performance as I'm developing. But then I do think there is a moment where you can go back and do instrumentation and measurement and really kind of identify where the bottlenecks are and then dig into how you can optimize those points as well. So I'm kind of a hybrid approach, always be thinking about it, but also have performance passes as well. Yeah,

Benji Lightstone:

I think that makes a lot of sense. If you're just thinking about performance while you're doing your initial implementation, it doesn't take that much more effort and it might save you a lot of headache down the line. And I think to really think about it easily, you need to have done some performance optimization. Once I went and spent three months doing this, now it's very easy to think about when I write code or review a pr.

Jamon Holmgren:

That is a fantastic point. Once you've done those deep dives, then it embeds it in your brain more for future stuff. I know that that's the case for me. I was helping my brother who is doing some game development au and he was writing some very naive code. He's younger than me, less experienced, and I was like, you're going to run into a problem later with performance on this. And I know he is just trying to get it working, but it's just something that I can't turn off. How have you dealt with cross-platform differences? You mentioned about Android having a certain native library that wasn't maybe quite as optimized or set up for success for Android. Other than that, what other cross-platform differences have you run into?

Benji Lightstone:

Yeah, that's a good question. I've run into a couple. Two of them were on, so I mean there's one that everyone's probably familiar with Safe Area view only working on iOS, so that's a bit more challenging On Android. There's two that are a bit more specific to our app that I've run into. So one is, and I could be wrong, and they may have updated it or I may just not have understood how it works properly, but we run our Android app in full screen and the use window dimension hook from React native doesn't actually account for where the Android navigation bar would be. So when I try to get the height of not the screen, but the window, because I always do window height because I want to make sure if you want to multitask, then that works properly. So we actually noticed that a lot of our modals, for example, the overlays which we're using the window height were had a bar that didn't have an overlay at the top or the bottom. So that's one that I ran into. And then a second one was a very gnarly bug. We were implementing in-app purchases so that developers could sell things in an item shop.

It worked great on iOS and we had it working on Android, but we noticed that when a modal would pop up to say, Hey, do you want to buy this? You click confirm, brings up the Google Pay sheet, which is, even though the app is in view, it's actually from the Android lifecycle perspective, it's backgrounding it because now the payment sheet is focused. And then when we came back afterwards, the app was frozen. It wasn't working. Okay. Wow. Yeah. So it's like, all right, me and a couple other people are working on it. And our VP of engineering, Mike, noticed that usually we couldn't figure what we didn't know what was happening. You press the button on the modal to say like, okay, confirm, and it doesn't do anything. Our avatars usually sway a little bit back and forth, and our VP of engineering, Mike, noticed that the avatar is not swaying.

So he's like, okay, I think the unity is paused and it's like something's happening where Unity is not actually active right now and the modal. So we have two separate pieces of state repositories. Essentially we have our React native context, and then we also have state that lives inside Unity, which gets synced into the React native context. This modal was actually being controlled by Unity. So because Unity was paused when you tried to dismiss it, the visible was not changing the visible flag. Wow. And this was something a time where I had to go learn more about the Android, the Android lifecycle, because I wasn't too familiar with it. And sure, essentially what happens is when you open a modal and React native, that's a different activity. So that activity is focused, which is totally fine unless you leave the app and come back to it. Then it doesn't refocus the main activity that everyone's probably used to seeing in their React native Android code. It keeps the focus on the modal and therefore Unity was not, it needs to call Unpause when you come back to the app. Basically, I exposed a method that allowed us to unpause it manually when we came back. Anytime that the React native code saw that it was foregrounded, then we can Oh, I see. Yeah. We can basically use that event listener from React Native.

Jamon Holmgren:

So React Native was able to kind of just watch what was happening and then say, Hey, wake up. We're good. Yeah,

Benji Lightstone:

Exactly.

Jamon Holmgren:

Wow. Yeah, that would be a weird bug to deal with. And this is sort of like what happens when you're dealing with different renderers and different engines kind of working together. And that will actually bring up, I think, a really important question. My last question to you, which is looking at what you've built and kind of how this all orchestrates together and everything, do you think that this architecture using React Native and Unity together to kind of combine into this as well as the host platform, so iOS and Android, do you feel like that kind of hybrid marrying together of technologies was the right technical choice? And would you do it again?

Benji Lightstone:

That's a good, really good question. I didn't work here when the app was conceived. I've spoken to people at Spatial about why we made those decisions, and of course take it with a grain of salt because I haven't done it the other way, but I think so I think this would be the right approach based on just the information I have now because our web dev, someone who knows React can easily work on the app. We can reuse the whole networking layer from web, and the one thing I might change is exploring Expo to deal with all the build issues. I think the biggest problem that we run into. So that's one thing that I would want to explore.

Jamon Holmgren:

Yeah, that makes sense to me. Thanks so much, Benji. This has been fantastic. I really appreciate you sharing all of your knowledge. I know that people are going to have more questions, things will come up. They're going to be really curious about this. Of course, the app's name is spatial. I was able to find it very easily. Obviously I was playing a game actually while we were prepping. It was super fun. Where can people find you online if they want to get in touch?

Benji Lightstone:

I think the easiest way to find me would be on LinkedIn. So if you just search for Benji Lightstone or Benji at Spatial, you'll find me on LinkedIn and pretty responsive there.

Jamon Holmgren:

Perfect. Awesome. Well, thank you so much. I really appreciate you joining us and helping us with our new Real Life React native series.

Benji Lightstone:

Yeah, thanks for having me. Jamon. It was great to tell a spatial story.

Jamon Holmgren:

If you'd like to be on this new series and talk about your experience using React native in the real world, email us at RN Radio at Infinite Red and introduce yourself and your app. This episode was sponsored by Infinite Red, my company, which is a React native consulting company. Get in touch if you need help with your React Native app. We'll see you all next time.

Jed Bartausky:

As always, thanks to our production team with editor Todd Werth, our assistant editor, this guy Jed Bartausky, our director of marketing and episode release coordinator, Justin Huskey and our guest coordinator, Derek Greenberg. Our producer and host is Jamon Holmgren and executive producers and hosts are Robin Heinze and Mazen Chami. Thanks to our sponsor, Infinite Red. Check us out at Infinite Red slash React native. A special thanks to all of you listening today. Make sure to subscribe to React Native Radio wherever you get your podcasts, and leave us a review. We'd love to hear what you think.