React Native Everywhere

Bookmark

Developing for each platform individually is so 2010s. These days, with React Native’s component system providing base-level UI constructs, we can efficiently develop for every platform while not sacrificing any particular platform’s uniqueness. Taz will review the approach they’ve taken while developing Guild, and the creation of their Mondrian cross-platform responsive design system as well as how they’ve accommodated the differences in navigational experiences across platforms to accomplish a codebase that can be 95+% shared across every platform.

by



Transcription


For those of you that don't know me, I'm Taz Singh, and I'm here to talk about react Native Everywhere, and as Katalin mentioned, by everywhere, yes, I mean everywhere, even down here with these lovely little penguins. For those of you that don't know me, I'm the founder of Guild, it's a new platform that's in beta at the moment, aimed at elevating communities around the world. Currently we're focusing on events, like the one we're at, and presentations, like the one I'm giving, all hosted on the same platform. So come chat with me later if you're curious about what we're building. But I'm sure by now you might have noticed that my accent is certainly not from around here, and that's because I started the Toronto JS community back in 2010, which is actually where I'm from, and as Katalin mentioned, for those of you that have questions, I actually got these coveted Toronto JS and Canada JS stickers for you if you ask a question, so feel free to come get one from me after. These are in very hot demand, so if you find a Canadian and you have one of these, they might just steal it off of you. Anyway, back in those early days in 2010, I was subject to a lot of banter about javascript. They said, oh, you aren't a real developer unless you program in.NET or Java or C++ back then, and I was taken aback, because back in those days, if you ever built a javascript application, it was immensely complex in nature. In the early 2010s, we were just starting to build apps using backbone and underscore, which were insanely complicated. So I started Toronto JS just to get folks together and learn from each other to elevate our craft together. A lot of what we did back then serves my impetus for starting Guild today and being involved with communities around the world, because I quickly discovered that communities like Toronto JS are everywhere. We're at one here right now. In fact, a lot of my closest friends are friends that I met through the community. Some of whom are here in this very room. And so I packed my bags in 2017 to move to London to explore those communities around the world, and that's when I was also introduced to react Native on every platform. And so you can see me here giving a talk about that in London just after moving in 2017. This is a tweet from Ellie, an organizer of that event where I spoke, actually an emcee here as well, and also a very good friend. You can find that presentation posted on Guild. If you head over to my profile, click on the presentations I've given, clicking on six and one will take you to a video I gave of the talk back then. But just to give you a very quick rundown of that talk today, essentially the goal is to have common code running on every platform. Of course, each platform is different and requires unique considerations to properly address each platform's advantages, and that, in my opinion, is one of the core strengths of react Native. To keep the codebase... To keep the core of your platform common while pushing the uniqueness to the boundaries. Things like date selectors, file inputs, notifications, maps, and more can be addressed at those edges, leaving the internals of your application to focus on the actual common experience. For an early stage startup like ours, it's important to optimize for developer efficiency. We want every change in our codebase to be as impactful as possible. We don't want separate teams working on each platform that will result in no code sharing at all. We don't want some sort of low level of code sharing where maybe some elements are shared but the majority is still separate. That would just be inefficient. In an unrealistically ideal world, we want all of our code to be shared across every platform but that wouldn't address the uniqueness of individual platforms and in my opinion, react Native makes it easy to address each platform's advantages. Realistically, we want the vast majority of our code to be shared across every platform, aiming for 95 plus percent code sharing and making our developers as impactful as possible. So go check out my talk I gave in 2017 where I speak about this in more depth and also include all the webpack config to make that happen. I've been striving for this result for the past five years or so and I'm happy to talk to you about the next part of my journey. But if you want to get started today, all of that's included in Expo. I really enjoy how they packaged all of that up and made it easy for you to just get started within every platform codebase. I'd recommend checking out the documentation. Make any app. Run it everywhere. So today I'm here to talk about the next part of my journey, starting with responsive composition. It's no secret that multiple form factors exist. When building an app that works everywhere, you obviously need to take this into account. You'd expect a platform like react Native to do this well but it really just provides the basic primitives and critically, there's no css which means there's no media queries, there's no css grid, there's no css selectors at all. There's no first child, last child, end child, none of that. And so styling in react Native is inspired by css and that there's css property names and there's a Flexbox implementation but css itself doesn't really exist. So if you've ever built a responsive web application before using these types of primitives and suddenly not having them, you can start to understand how difficult it can be to build a truly every platform experience using react Native. So what do I do? Fortunately, I went to consult in Bangalore back in 2017 and the community the organizers of the community there got in touch with me to present for their community because communities are everywhere after all. So I agreed and here I am presenting on a Pontiac Aztec. It's a truly magnificent car. I had the pleasure of getting to know the organizers of that community, one of which is Siddharth who's sitting next to me in this photo and thank goodness for that because he's now one of the foremost experts in the react design system space who I look up to for knowledge in that area. So around the same time in 2020 when I was trying to figure out a design system for my react Native application, Sidd came out with react UI. So this is taken from the react UI website itself where it says react UI comes with a set of components that are accessible, responsive, and customizable. That sounds like exactly what I want. It also has a list of components that it ships with. So reading from the right, there's element, link, select, text, text area, and so on. It has everything. Critically at the bottom, there's also stack and grid to help me build a layout with those other building blocks. But the fundamental problem was that react UI is built for web and what I want needs to be compatible with react Native. So it got me thinking. Maybe I could just create the same thing but for react Native. And so I tried doing exactly that, but after a bunch of trial and error, I finally got something working. And so I thought to message Sidd. Like I said, hey, dude, how's it going? Enjoying Amsterdam? Wanted to reach out to say I'm a big fan of react UI. In fact, such a big fan, I ended up implementing large parts of it for react Native in a cross-platform manner. It's a shameless rip of react UI, but of course react UI is for the web and what I've built is for react Native. That's no emotion, no css, had to implement stack a bit differently, and so on. Sidd kindly responded, that's really cool. react UI is ripoff theme UI, ripoffs all the way down. And so as I've been known for saying, good artist copy, great artist steal, right? But looking at the dates on those messages, it was peak lockdown 2020 that I was working on this, and I'd like to show you what I built. So here's an example of that, and this is actually powering the Guild web experience right now. So if you go to guild.host, you can check this exact thing out live right now. So fundamentally if you look at the code on the left, you can hopefully just see how it renders the experience on the right. The critical construct that makes all this composable is that stack component. All I have to do is set the gap property and the rest just renders based off of that. No more passing down a style prop through everything, no more style prop drilling or whatever you want to call that. You just set a gap and that's it. Everything just works. Now at the bottom I have that user item component, which I pull up the code for here. You can see again, it's just a stack once again. That's horizontal this time. It renders a user's primary photo and a link component with the user's name. Everything is highly declarative and highly composable. I just need to add more elements to this page and the rest will just automatically layout based on that stack gap property. That's it. Horizontal, vertical, whatever you need. That's basically all it is. I think by just composing stacks in this way, this is what's called being a full stack developer. Now we can take all of that and put it in a grid, which you can see I have here. Each stack is a row and we have a grid with columns within each row. By simply composing these stacks into a grid with columns, we can build the entire responsive experience on the right. That's it. I've shown you all the code directly from my production code base. Nothing hidden. This is exactly what's powering GIL today. And as you can see, I'm quite happy with it. I'm showing it all to you here right now. I'm quite proud of basically what I built during that time. So I'm pretty happy with the implementation. You know, I want to share it with all of you. And it was really gearing up towards a public release of all of this. But first, obviously, you've got to come up with a cool snazzy name. So I came up with the name Mondrian. Was inspired by the famous Dutch design system engineer Piet Mondrian, known for composing stacks into UIs like this. So I created an empty repo on GitHub, started preparing for a public release, and I was really excited to share Mondrian with all of you in the rest of the world. And that's when I found out about NativeBase. So for those of you that aren't familiar with NativeBase, let's compare it to Mondrian. First of all, NativeBase is also in every platform react Native design system. It works everywhere. It's far more comprehensive than what we built. They've released their third version. They're on 3.4.19 and we've on alpha 3. They spent far more time on accessibility than we have. I don't think we've thought about it much yet. But they've spent a lot of time thinking about it. They have docs and we don't. And fundamentally, most importantly, they're built in Bangalore, which was the core inspiration of Mondrian and my whole design system experience all along. So these days, if I was to recommend a solution, I would recommend just start with NativeBase. They've done a fantastic job. It's very well done and it functions everywhere. But I'll take a small step back for a minute. Since writing this talk and presenting it and meeting fantastic people like Katalin and so many other friends while giving this talk around the world, I've had the pleasure of learning more about what the latest happenings are within design system space and I've come to know for another one. Tamagui. I'm not even sure if I'm pronouncing that properly. Tamagui? I don't know. Tamagotchi? Tamagui. The creator of Tamagui, Nate, he liked the term react Native everywhere so much that he borrowed it for his own website. He went on to say that Tamagui, or really I think this applies to react Native design systems as a whole, covers about 40% of the cross-platform experience just by code sharing through the design system context all on its own. And for me personally, it's just great to see more contenders in this space. It's good to have more options when building a react Native design system and it's also great to see the community evolving and taking this space more seriously. And so going back to the example I mentioned before, where are we now with our 95 plus percent code sharing journey? So if Tamagui mentions that they give 40% of that, composing that upwards into screens or pages maybe brings us to 60%. Another 80% is maybe provided by a data layer. But then what's remaining in that bottom section there? What's left to bring us to 95 plus percent? And really that's the next tier of what we're kind of figuring out right now within the react Native space, and that's navigation. Navigation has been historically difficult and challenging to solve across every single platform. Because fundamentally there's internal navigation, and what I mean by that is where you navigate using the UI itself, the actual navigational experience is internal to the UI, and that's what you'll find on a mobile experience where you'll tap a button and you'll navigate to a new page, you'll tap a back button within the UI and navigate backwards. The main exception to that is Android's back button, of course, which is external to the UI, but I won't spend a lot of time getting into that one. Then of course there's external navigation like what we find on the web. And so if you use a browser before, you're familiar that there's a back button, a forward button, a refresh button, and a URL bar as well as tabs, all external to the UI of the application you're building. All of these manipulate the navigational state of the application entirely external to the application itself, of course. So I don't have to explain how a browser works, but the main thing is the URL bar, and so that's fundamentally different and lacking on an internal navigational experience, but is present on an external navigational experience. You should be able to copy that URL into a new tab and it should just load that same page for you. It should all just work. And to demonstrate an example of that, I have a recording of my cat's Instagram page. She's too adorable, isn't she? If we navigate using the UI, like, internally to that experience, you can see a modal opens up and it opens up contextually over what's behind it because it knows what's behind it because all of that application state is handled by the application itself. This is similar to how mobile and desktop navigation could work. But as you can see, copying that URL into a new tab opens the same page but it doesn't know what to put behind it. So it renders that as an entirely full page. This is, again, like, external navigation working on the web. So really to build in every platform navigational solution, we need to support both. Internal navigation and external navigation all within the same experience. And this has been historically very challenging to do, especially in react Native. So how do we get building on this? Well, there's react Router, of course, which advertises support for browser-based DOM routing as well as react Native. And while this works very well, it lacks the native bindings on mobile to do things like dragging from the side of the screen to navigate backwards. It just doesn't feel native. The state management works but it doesn't feel native on those platforms. Then there's react Navigation, which is a full-on mobile-first navigational experience. If you've worked with react Native before, you've likely used react Navigation. It uses react Native screens from Software Mansion to provide that drag from the edge of the screen to go back functionality. And on mobile, it works great. In recent years, they've also shipped web support, as I'm showing here. And so we ended up trying this at Guild. And it just didn't quite feel proper on the web. While it technically works, a bunch of things just felt off. Things like incremental loading of routes, which you obviously want on the web. You don't want to ship everything in one massive payload. It would also rewrite the URL bar incrementally as well. So you see the URL bar rewriting itself as you waited for the rest of the page to load, which just felt odd. And if you press the back and forward buttons, it would put the app into a weird state that we just couldn't recover. And so you would go and refresh it again, and then the URL bar would rewrite itself again. And so it just felt entirely off. But to summarize, then, basically react Router has great state management, but it doesn't feel native on non-web platforms. And react Navigation state management is a bit wonky, but it has that native feel. So if we're aiming for 95 plus percent code sharing for every platform, we've picked react Navigation despite its flaws in the web. The UX won't be ideal, but at least the users will just have to live for it for now. Its wonkiness is just the best we have. And I know the team there is smart, and they're working very hard on this. I know them very well, and I know that they're putting a lot of time and effort into this. And so I've tried to lend a hand by sending in pull requests, but the state of the code base was just beyond my comprehension to actually properly contribute. So we'll just have to wait and upgrade as they release new features. The user experience will hopefully improve after every release, and that's really the best that we have today. So that's basically what we went for. More recently, speaking with other folks in the community, they've all told me about Solido. There's been a lot of marketing around Solido solving cross-platform navigation. And so my view is that Solido makes it easier to manage a web navigation stack powered by next.js, separately from a native navigation stack powered by react Navigation. You have two entirely different navigational stacks. That's how this solution gets around the types of challenges I mentioned before. You can see in their docs when creating a route, it requires you to define a route on the web and then separately define another route entirely on native. It's two entirely different navigational stacks. By design, this is not 95 plus percent code sharing. This is two entirely different navigational stacks. And Solido does a fantastic job of making it easier to manage two different navigational stacks, but it's not really what we're looking for if we're focused on code sharing. If it was code sharing, that would be just one step. You just create a screen. That would be it. So on my travels I mentioned earlier, I was fortunate enough, however, to bump into the expo team in April back at react Miami. Because communities are everywhere, after all. react Miami was a fantastic community. I'm here with Brent, a core maintainer for react Navigation, as well as Evan and Charlie. I had such a good chat with them that I said, hey, Evan, we got to chat a bit more about the frontier of every platform react Native development. And so the next day we sat down to chat about build tooling, navigation, bundling for expo and react Native and recorded it all for our YouTube channel. You can check that out down below. He had some amazing ideas back then in April and six months later it's awesome to see it finally come to fruition in expo router. Honestly, this looks amazing. To create a screen, you just create a screen. That's it. It's one step. You're done. Fundamentally, it unifies native routing around URLs, which makes it far easier to author your navigational stack across every platform as a URL path is a first class construct everywhere. Another nice side effect of this is deep linking on mobile is dramatically easier. You just refer to the same URL as you would on web. URLs, who would have guessed that solved navigation? This router is in beta at the moment as the expo team is seeking feedback to refine it before an official public release. It's not quite ready for us to use in the web, in my opinion, because it still only supports the metro bundler, which doesn't do code splitting. It still ships everything as one gigantic payload. But again, this is really feedback for the team to see if this approach works. Speaking to the team, the next thing they'll be working on is proper web based build tooling and bundling for this. So I'm super excited about the direction of this. This looks legitimately amazing. 95% plus code sharing is possible because of this and I can't wait for the final release of it being officially possible. But as I mentioned before, it's not quite there yet. And so for now, we just have to stick with react navigation and kind of go through all the flaws that that has. And so that's really my talk. Thanks. Thank you very much, Naz. Oh, I fooled you. Oh, there was another one? I can't end a talk like that. Come on. What do you think? What do you expect? I mean, I even fooled Katalin. That's a terrible way to end a talk. Are you kidding me? There's no real solution at the end of that. Why would you think I would leave you all I'm disappointed in all of you. Disappointed in all of you for that. Come on. You should expect more out of me. So by now you should know that if I solve all my problems in the community with incessant complaining to members of the community. And so this time it was complaining to my good friend Lorenzo, pictured here at my friend's Phil and Cindy's wedding. It's the only photo I have with him and it's too bad he's just not here today. We need to take another picture with him. You know, just me and him this time. So just to resolve any ambiguity here in case you're wondering how this works, reading from the left to the right, I'm clearly the best man and Lorenzo's clearly the second best man and there's no other way to interpret this photo and it's a good thing Lorenzo wasn't here to tell you either. But anyway, Lorenzo is also a former maintainer of react navigation and also heavily involved with react Native community efforts. Oftentimes when I don't know if a good way to proceed in the react Native space, I just go ask Lorenzo because he tends to know about community happenings before a lot of the rest of us do. And this time he came through. He told me of a new library called react Native URL router and that sounds like exactly what I want. A react Native router but with URLs. And so I took a look at their documentation and I found this example. So I'm not sure if you can see the small text on the left but basically it's all the best parts of react router and their excellent state management mashed together with the best parts of react Native screens to provide that drag from the edge navigational experience that's native to mobile. This looked amazing. So I went to try it out and found it just did not work at web at all fundamentally. Just didn't compile. Just didn't work. It's still experimental. Still built mainly for mobile. But adding web support looked pretty straightforward. If you can see that red outline there, it looked like just swapping out those two components and that's it. Swap out a native router for a browser router and swap out a stack navigator for just a route component from react router. Swapping out two components made it look as if the rest of this would just work very well on web. But I didn't want to go through all the effort of sending PRs over only for the maintainers to reject them during review due to not being aligned with their direction and so I wanted to check with the maintainers before contributing essentially to this project. I got in touch with Alec from Software Mansion and asked if we could have a quick chat about the direction before I started just sending over PRs. And what I got really surprised me. Alec set up a call and invited Christoph who I looked up on LinkedIn beforehand because I didn't know who he was. It said he's the director of engineering at Software Mansion and I was gearing up for like a well Taz. We're a consultancy and if you want to hire us as a consultancy, here's our rate sheet and we'll happily help you out with anything you need based on that rate sheet. But what I got instead really surprised me. I got so much support and kindness from both of them that I was really taken aback. They told me that they're here to help with any aspect of using their library and they didn't ask for anything in return but kind feedback on ways we can improve together. In fact, they were more interested in the direction of Guild as a platform and wanted to help support the community effort along with us. I have to say, I've been in the software business for over two decades now. I don't think I've seen so much love and dedication to the craft as I've seen from these two. It was honestly amazing. I can only speak of them in the highest and would recommend you check out their community efforts as well. So we agreed to partner up on react Native URL router to use Guild as an example app of how that works as a production-ready full-fledged application and we can test out the paradigm, fix any kinks and kind of get that library working for everyone out there in the community as well. So I rolled up my sleeves, I rewrote our entire app, I ripped out that react navigation and dropped in react router as a stepping stone towards react Native URL router and here are the stats from that PR. As you can see, I removed more than double the code that I introduced and overall the app feels much snappier now because all the browser-based navigation feels much more at home. I think the best way to ask if it was worth it is to ask you, did you even notice? Did you notice that Guild is using react Native web? Did you notice that Guild is built using an experimental home-grown design system? Did you notice that it's also using an experimental navigational framework as well? Or did you just think it was an ordinary app built in ordinary ways all along? I spoke a lot about running on every platform but right now we're still focused on just the web but we hope to incrementally release a mobile and desktop app in the future because our entire infrastructure is built to accommodate that. It's much easier releasing that from where we are today than starting a whole new codebase. But if you've taken away anything from this talk, it should be that we're only as good as the community around us. Throughout this journey, I'm fortunate and privileged to have met the people I've met through the community. Without them and without their support, I would be nowhere at all. It's not like I'm special. I just go to events and I talk to the people there and I learn from them. That's why we started TorontoJS back in 2010 and that's why we're working on Guild now. Because at the end of the day, communities are everywhere and now your technology is too. Thank you. Thank you so much, Tez. Thank you so much. Is it okay now? Nothing was prepared, by the way, but it was really, really nice at the end. So yeah, thank you so much for the talk. Thank you. Oh, yeah, we have enough time for some Q&A. Sorry about the previous talk. If you have asked something, it seems that I haven't moderated the forum. So go ahead to Lorenzo and ask the question personally. And Lorenzo's here? I think there are some nice questions anyway. So please do so. And I feel sorry about that and really bad, yeah, shameful. So speaking about questions, I haven't... Right now it's auto-moderate off, so if you're doing something, you'll be able to see it on the screen. But I have prepared some questions on my own. Where do you see react and react Native in the future in terms of embeddable components? I'm so happy you asked that question. So essentially our journey and commitment to react Native everywhere is we mean very literally everywhere. And so right now, as I mentioned, five years ago, we were kind of obsessed with how does this physically execute on every platform? What's the method of execution to run the same code across every single platform? And that was kind of the forefront of five years ago. Today it's design systems and navigation, and I'm super happy to see tons of great solutions out there, as I obviously talked about in my talk. But I think to have... I swear that's not me! And so I think the next frontier will be embeddability. How do we take the experience that we've built and how do we place that where the traffic exists? For us at Guild, obviously we're an event-driven website. Events include ticketing, for example. You might have a conference website, you might want to put the ticketing experience on the conference website. That requires embeddability of an experience. And so it's our view that that will be the next frontier of how do we embed across different web experiences, essentially for react Native everywhere. Conversely, how do we embed across mobile experiences? How do you take the same experience, embed that within another app? How do you take that same experience and stitch it in seamlessly anywhere? We've done experiments of stitching in react Native into Flutter, because at the end of the day, they're both reporting down to native mobile views. It's technically possible to stitch in native views. You can stitch in one native view powered by react Native into another native view. The same thing for stitching in react Native into any web experience out there as well. You simply need to wrap it in a container and then you can kind of ship it around. And so I think a lot of this work falls back into the work on micro frontends. And so I know Alex and Ruben are here to talk about that as well. But that's kind of the next frontier as we think about it is how do we go from where we are now into creating a truly embeddable every platform experience. That was a really, really nice answer. Thank you very much. And actually to close this entire react Native track, I would like to ask you why do you think communities matter? Well, I think for me it's personal. For me, I was really enabled. I'm here today because of the community. I've learned everything I've learned through the community. Learned through events like this and smarter people out there that I just happened to talk to and kind of learn from them. And so I think yourself and your YouTube channel has probably thought and inspired so many great people out there as well. And that's really just a community at the end of the day. And so for me, because I've taken so much from the community, I feel like I should give back. And I think that's why it means so much for me is on that personal journey. But I kind of hope that for all of you out there as well, you can also learn and appreciate in the same ways that I do from obviously you're here today for that reason. And so, yeah. Yeah, with that, yeah, thank you very much, Taz, once again. And just give a round of applause. And also, since we have two more minutes, I think that it is smart to ask Lorenzo to come in and take a selfie with the hour. I don't know, someone, we have like a pro photographer here that can help us out with the photo. This guy. There we go.
29 min
21 Oct, 2022

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Workshops on related topic