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.
React Native Everywhere
AI Generated Video Summary
React Native Everywhere enables code sharing and platform individuality, responsive composition and navigation are key focus areas, the React Bangalore community has played a role in the development of React Native design systems, React Native URL Router provides a native feel with drag-from-edge navigation, collaboration with Software Mansion has been beneficial, and token-based centralization is important for consistent adaptation of design systems.
1. Introduction to React Native Everywhere
I'm Taz Singh, the founder of Gild, a platform aimed at elevating communities around the world. I started the Toronto JS community in 2010, and now I'm in London exploring communities worldwide. I was introduced to React Native on every platform, and its core strength is the ability to have common code run on every platform, while addressing each platform's uniqueness. This optimizes developer efficiency.
♪ I'm Taz Singh, and I'm here today to talk about React Native everywhere. And by everywhere, yes, I mean everywhere, even down here, with these lovely penguins.
For those of you that don't know me, I'm the founder of Gild. 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 right now, 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 the platform.
So I packed my bags and moved to London in 2017 to explore those communities around the world. And it was also then that I was introduced to React Native on every platform. Here you can see me giving a talk about that in London just after I moved. This tweet is from Ellie, who's actually just over there. She's an organizer of that event where I spoke and now a very good friend as well. You can find that presentation posted on Guild by heading over to my profile, clicking on the presentations I've given, or clicking on 6 and 1, that will take you to a video of the talk I gave back then. So feel free to check it out.
But to give you a very quick rundown of that talk, essentially the goal was to have common code run on every platform. Of course, each platform is different and requires unique consideration to properly address each platform's advantages. This is one of the core strengths of React Native. We can push that uniqueness to the boundaries and keep the core of your code base common for every platform. Things like date selectors, file inputs, notifications, maps, and more can be addressed along the edges, leaving the internals of your application to focus on the common experience. For us, an early stage startup, it's important for us to optimize developer efficiency.
2. Code Sharing and Platform Individuality
We want every change to our code base to be as impactful as possible. React Native makes it easy to respect each platform's individuality and create truly unique mobile experiences. Realistically, we aim for 95% plus code sharing across every platform.
We want every change to our code base 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 low level of code sharing that maybe some elements are shared, but the majority is still separate. In an unrealistically ideal world, we'd want 100% 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 respect each platform's individuality and by leveraging that you're able to create truly unique mobile experiences, or sorry, native experiences. Realistically, what we want is the vast majority of our code shared across every platform, aiming for 95% plus code sharing and making our developers as impactful as possible.
3. Responsive Composition and Navigation
Today, I'd like to focus on responsive composition and navigation. React Native provides the basic primitives for building apps that work across multiple form factors. However, it lacks CSS, making it challenging to create responsive UIs without familiar web-based constructs. Let's discuss composition. When rendering a list of items, adding padding and spacing can lead to inconsistent results. The code becomes repetitive, requiring the passing of style props for each component. This approach is cumbersome, especially in a team setting. The composition needs improvement.
Of course, feel free to go check out my talk from 2017 where I speak about this more in depth and I also include all the webpack config to make it happen. But these days, all of that is packaged up with an expo. So take a look at what they have. I'd recommend checking out their documentation and they have great guides on getting up and running with a platform to run on every platform. Make any app, run it everywhere.
So today I'd like to focus on the next stage of my journey, responsive composition and navigation. Let's start with responsiveness. It's no secret that multiple form factors exist. When building an app that works everywhere, we obviously need to take this into account. You'd expect a platform like React Native to account for this, 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. Styling in React Native is inspired by CSS in that they use CSS property names and have a Flexbox implementation. But CSS itself doesn't exist in React Native. If you've ever built a responsive web application before, you can start to see how challenging it is to build those same UIs without any of the web-based constructs that you're used to.
OK, so let's talk about composition. Let's assume you have React Native code that looks like this, with a rendered UI on the right. We're just rendering a basic list of items here. The design doesn't really look that great. So let's add a background color and some padding to that container. OK, now the items are a bit squished together as well. Let's add a bit of spacing between those. And so you can see that the bottom three items have a padding top applied but the top one doesn't. And that's because if we apply the same padding, it would be too much padding with the container as well. If we removed the container padding, then we'd mess around with composition, where if we have multiple of these rendered within the same container, the padding would just be off throughout. And the code is also quite repetitive. We wouldn't really write code like this in reality, so we'd refactor it to something like that, where, as you can see, the array that we're mapping over might be data from a server or something. And we're really looking at the array index to determine what styles to apply. So, fundamentally, I find myself doing this quite a bit and trying to pass down that style prop for every single component. I found you had to kind of police the style prop passing, which is kind of annoying when you have a team of developers and you're trying to make sure they're passing it down correctly. The composition just didn't work.
4. Introduction to React Bangalore Community
I went to consult in Bangalore in 2017 and had the opportunity to present for the React Bangalore community. I got to know the organizers, including Sid Dart, who is now a leading expert in the React design system space.
So what do I do? Well, fortunately, I went to consult in Bangalore in 2017, and the organizers of the React Bangalore community got a hold of me and asked if I wanted to present for their community. Communities are everywhere, after all. And so I agreed, and here I am talking about a Pontiac Aztec. It's a truly magnificent car. I had the pleasure of getting to know the organizers of that community. One of them is Sid Dart, who's sitting next to me in this photo, and he's actually speaking on the other stage. I'm not sure if this is the first time the speaker's been on both stages at the same time. And thank goodness I met him, because he's now one of the most foremost experts in the React design system space, who I look up to for knowledge in that area.
5. React UI and Composable UI
Around the same time in 2020, I discovered React UI, a set of accessible, responsive, and customizable components. Although it was built for the web, I wondered if I could create a React Native design system using its layout constructs. After implementing large parts of React UI for React Native, I messaged Sid, who responded positively. The critical construct that made everything composable was the stack component, allowing for automatic spacing and easy composition. By combining stacks within a grid, we achieved a fully responsive and declarative UI.
Around the same time in 2020 that I was looking for a solution for my React Native application, Sid came out with React UI. This was 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 has a list of components that it shifts with, I'm just reading from the right there, there's element, link, select, text, text area, and so on, and critically at the bottom, there's also stack and grid to help you build a layout with those other building blocks.
But the problem was, React UI is built for the web, and what I was building was for React Native everywhere. But I wonder if maybe I could create a React Native design system, maybe those layout constructs could help me with the responsive composition of my React Native applications, and so I tried doing exactly that. After a bunch of trial and error, I got something working, and I thought to message Sid. I said, hey Sid, how's it going? Enjoying Amsterdam? I 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 off of React UI, but of course React UI is for the web, and what I've done is for React Native. Thus there's no emotion, there's no CSS, I had it stack a bit differently, and so on. Sid kindly responded, that's really cool. React UI is a rip-off theme UI, rip-offs all the way down. As I've been known for saying, good artist copy, great artist steal, right? Looking at those dates on those messages, you can see this was peak lockdown in 2020 that I was working on this, and this is a picture of what I built back then. You'll see this if you go to the presentation screen on Guild. And this is straight production code, straight from our codebase. Hopefully just by looking at the code on the left, you can see how it maps to essentially to the UI on the right.
The critical construct that makes all this composable is that stack component. Where I just have to set the gap property, and the rest renders based off of that. No more passing down a style prop, and in order to set all the spacing, everything just works automatically. At the bottom I render a user item component, where if I pull up the code for that, and highlight that with a red dotted line, you'll see what's rendering there as well. Again, it's just a stack. This time it's horizontal, it renders a user's primary photo, and it also renders a link component with a user's name. By simply composing stacks, we're able to write our entire UI in a manner that glues together nicely. I think that's what they call being a full stack developer. We can take that, and place it within a grid, which you can see here. We can take the stack, which has a grid with columns within each row. Again, by simply composing these stacks into a grid with columns, we can build that entire page on the right. As you can see, it's fully responsive while also being highly declarative. Ok. So at this point I was pretty happy.
6. Mondrian and Native Base Comparison
All of Guild is built in this way, and it seems to work quite well. Mondrian is a React Native design system inspired by Piet Mondrian. Native Base is a more comprehensive design system with accessibility and documentation. For navigation, mobile and desktop have UI-based navigation, while web-based navigation includes external controls like a URL bar. Pasting a URL into a new tab should work seamlessly.
I got it working. All of Guild is built in this way, and it seems to work quite well. So I came up with a snazzy name. Mondrian. It's named after the famous Dutch design system engineer Piet Mondrian, known for composing stacks into UIs that look like this. And so I created an empty repo on GitHub and I started preparing for a public release. I was really excited to share it with all of you. But that's exactly when I found out about Native Base. So let's compare Native Base with Mondrian, shall we?
Alright! It's an every platform React Native design system. It's far more comprehensive than what we've built. We're at 0.0.0 alpha 3, they're at version 3.4.6. They have accessibility. They also have documentation. And critically, it was built in Bangalore, which was the inspiration for Mondrian all along. So these days, I would also recommend a design system for you, I would say, just go use Native Base. They've done a fantastic job. I think a few of the team are actually here today if you want to talk to them.
Okay, so what's next? Navigation. Well, there's mobile and desktop navigation. And on these platforms, it's more typical to navigate using the UI itself. You tap on a button, you navigate somewhere else. Essentially, the UI is the core navigational construct without much else in terms of external controls in order to manipulate that UI. There's the Android back button, which is kind of the exception, but I won't get too deep into that one for this talk. Next up, there's web-based navigation, where the browser has a back button, a forward button, a refresh button, a URL bar, and tabs. Each of these manipulates the navigation externally, essentially to the application. I don't have to explain how a browser works, but the main navigational difference is essentially the URL bar, where you should be able to take that URL and paste it into a new tab, and it should just work. To demonstrate that, here's my cat's Instagram page. She's adorable, isn't she? If we navigate using the UI, if we tap on an image, it opens up in a modal. You'll see that there's a background to that modal, because it has the context of what to put in that background. However, if you copy and paste that URL into a new tab, there is no background.
7. React Router vs React Navigation
React Router has great state management, but it doesn't quite feel native on non-web platforms. React Navigation's state management is a bit wonky, but it has that native feel. When building a 95-plus percent shared code base with the same navigation for every platform, we pick React Navigation despite its flaws. The UX won't be ideal, but users will just have to live with that. The team is working hard to make it better, and we hope the user experience will improve with every release.
It opens as a full page for that image. And again, this is a core difference between mobile and desktop navigation, where mobile and desktop can work in the first case, but web has to work for the second case.
So how do we go about building this? Well, there's React Router, which advertises support for browser-based DOM routing, as well as React Native. And while this does work very well, it's not really built in on mobile to allow things like dragging from the edge of the screen to go back, like that really slick, Native-feel, it doesn't have that built in.
Then there's React Navigation, which is a full-on, mobile-first navigational experience. If you've built using React Native before, you've likely used React Navigation. It uses React Native screens from Software Mansion in order to enable that drag from the side of the screen functionality. And on mobile, it feels amazing, it feels great, it feels native, it feels proper. In recent years, they've shipped this support, as I'm showing here, and so we tried this, and it just didn't quite work very well. While it technically works, a bunch of things just felt heavy, and it just felt off. Things like incremental loading of routes, which you obviously want on a web experience. You don't want to load everything in one gigantic payload on the web. It just made the URL bar also evaluate incrementally. The URL bar would just rewrite itself, essentially as the routes loaded in. The back and forward buttons didn't quite work either, so if you click back, forward, back, forward, the whole app would just get in a weird state, and it wouldn't be able to recover, so you'd go and refresh, and then your URL bar would start rewriting itself all over again.
So, to summarize, React Router has great state management, but it doesn't quite feel native on non-web platforms. React Navigation's state management is a bit wonky, but it has that native feel, so when building a 95-plus percent shared code base with same navigation for every platform, we pick React Navigation despite its flaws. The UX won't be ideal, but users will just have to live with that, and the wonkiness will just be there. I know the team is smart, and they're working very hard on making it better. I tried lending a hand by sending pull requests, but it quickly became apparent that a library with the heritage of React Navigation requires more consideration than I was able to dedicate. But we'll just wait. We'll upgrade. I'm sure they're working on it. And as they release new features, essentially we'll have them as well within Guild. We hope the user experience will improve with every release. And yeah. That's my talk. Thanks, everyone. applause applause applause applause Come on. Come on.
8. React Native URL Router
I'm just kidding. That would be a terrible way to end a talk. There's no solution. I was complaining to my good friend Lorenzo, who told me about a new library called React Native URL Router. It's the best parts of React Router mashed together with the best parts of React Native screens to provide a drag from edge navigational experience with amazing state management. Adding web support looked pretty straight forward, just swapping out a native router for a browser router and a stack navigator with a route component from React Router.
I'm just kidding. That would be a terrible way to end a talk. There's no solution.
What? What? Jeez. I'm disappointed in all of you. If you've learned anything by now, I solve all my problems with incessant complaining to folks in the community. And this time, I was complaining to my good friend Lorenzo, pictured here at Phil and Cindy's wedding. It's the only photo I have with them. So reading from left to right, I'm clearly the best man. Lorenzo's clearly the second best man. There's no other way to interpret this photo. You can go ask Lorenzo, Phil or Cindy, and they'll definitely agree with me. No questions asked.
Lorenzo is a form maintainer of React Navigation and he's 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 him. Because he happens to know about things before the rest of us do. And this time, he came through. He told me about a new library called React Native URL Router. That sounds like exactly what I want. A React Native Router, but with URLs. So I took a look at the documentation page and I found this example. I'm not sure if you can see the small text, but in essence it's the best parts of React Router mashed together with the best parts of React Native screens to provide that drag from edge navigational experience with amazing state management. It looked amazing.
So I went to go try it out and found it didn't quite work on web at all. It's still experimental and it's only built for mobile. But adding web support looked pretty straight forward. It looked like it just required swapping out those two components right there. Swap out a native router for a browser router. Swap out a stack navigator with a route component both from React Router and it looked like it should just work. It looked very simple and very straight forward.
9. Collaboration with Software Mansion
I got in touch with a maintainer Alec from Software Mansion and I asked him if we could have a quick chat before I start sending over PRs to him. Alec set up a call with Christoph, the director of engineering at Software Mansion. They were kind, supportive, and interested in the direction of Guild as a platform. Their love and dedication were amazing.
But I didn't want to go through all the effort of sending over PRs only for the maintainers to reject them because it didn't align with their direction. So I got in touch with a maintainer Alec from Software Mansion and I asked him if we could have a quick chat before I start sending over PRs to him. And what I got really surprised me. Alec set up a call with Christoph who I looked up on LinkedIn before because I didn't know who he was. He's the director of engineering at Software Mansion and I was like oh no. I know what this is going to be. This is going to be one of those chats where it's like well, Taz, you know we're a consultancy and if you want our help you can just hire a consultee to help you and they're going to send a big bill over at the end of it. But I didn't actually get that at all. It was honestly so lovely and so kind. I got so much support and kindness from both of them that I was honestly very taken aback. They told me they were just here to help with any aspect of their library. They didn't ask for anything in return, but just kind feedback on ways we can improve together. In fact they were more interested within the direction of Guild as a platform because they wanted it to help their community efforts as well. And I have to say I've been in the software business for two decades now and I don't think I've seen so much love and dedication essentially than I've seen from these two. It was honestly amazing. I can only speak of them in the highest and I'd recommend you check out their community efforts as well.
10. React Native URL Router and Community Support
We partnered up on React Native URL Router, using Guild as an example app. I removed the entire app, replaced React navigation with React Router, and migrated to React Native URL Router. The app feels snappier with browser-based navigation. Guild uses React Native Web, a home-grown design system, and an experimental navigation framework. We aim to release mobile and desktop apps in the future. The community is vital to our success, and I learn from the people around me. Sharing basic design variables can be done using React UI's token system.
Long story short we agreed to partner up on React Native URL Router. We wanted to use Guild as an example app to test out the paradigms and make sure they all worked well. And so, I ended up rolling up my sleeves and I removed the entire app. I ripped out React navigation and I dropped in React Router as a stepping stone to migrate to React Native URL Router. These are the stats on that PR. You can see I removed more than double the code that I added. Overall, the app feels much snappier and the browser-based navigation feels much more at home.
I think the best way is to ask you did you even notice? Did you even notice that Guild is using React Native Web? Did you notice that Guild is built using a simple home-grown design system? Did you notice that it's using an experimental navigation framework as well? Or did you just think it was an ordinary web app built in an ordinary way? I spoke a lot about running on every platform while right now we're still focusing on web but we hope to incrementally release a mobile and desktop app in the future as our entire infrastructure is considerate of all these different platforms as well and releasing for them is far easier than starting a whole new code base.
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, I talk to the people there, and I learn from the people around me. That's exactly why I started TorontoJS back in 2010. That's exactly why we're working on Guild right now. Because at the end of the day, communities are everywhere. And now your technology is too. Thank you. Are you sure this time? Can I... I've been burned before. That was amazing! Thank you. Let's talk about it. Stay right there.
Hi Taz! No, no. Leave. Okay, the people want to know. Any tips for starting out sharing basic design variables between web, mobile, colors, font sizes, etc? Yeah, fantastic question. For me, I really just looked at React UI for this, so I'd recommend you do the same. I think Sid wrote fantastic documentation on exactly this. In essence, what he's done is he has a whole token system defined for his design system.
11. Token-based Centralization
Leverage centrally defined tokens to share and centralize variables, avoiding excessive customization on each layer. By keeping tokens centrally, it enables consistent and well-managed adaptation of the entire application and design system.
Then you can leverage those tokens defined centrally through a variant on every single building block of your application, and that allows you to effectively share and still centralize these types of variables. Essentially, what I found didn't work quite well is basically that style prop. If you pass that style prop down, then it enables too much customization on every single layer. So if you're off by like one pixel, the whole design just looks off. By keeping all of those tokens more centrally, it allows you to adapt your entire application, your entire design system, more centrally as well, and that keeps things very consistent and very well managed.