React Native for Web is one of the most amazing ideas I’ve stumbled upon in a while. For UI developers, it makes a longtime dream a reality: the ability to create an application that runs on both phones and browsers with just one codebase.
The path we followed to arrive at this point is also really interesting:
The need for the final step above is a bit unclear at first. We already have React, which was initially created to build web apps. Why would we use something else that wasn’t made to fit that explicit purpose?
The first reason is that React Native uses a kind of subset of React to generate the UI. If we want a code that runs in both mobile and web, we should stick with the more restrictive one; in this case, it’s React Native. As long as we don’t use modules that require some native functionality, a React Native app should work in browsers through React Native for Web out of the box.
The second reason — and what really makes React Native superior to React for creating universal apps — is that React Native is a pure UI language. It defines some base components that define UI primitives, and those are thought to be independent of the platform that runs them. All the components we can create in React Native are based on primitives like <View>
, <Text>
, or <Image>
, which are basic elements that make sense to any visual interface, no matter where it is run.
On the other hand, React’s primitives are just DOM nodes — HTML tags like <div>
, <p>
, or<a>
, which are not pure UI. They weren’t created to define a visual language; rather, they’re meant to structure and make sense of the hypertext. React’s primitives have meaning beyond the interface, and that meaning doesn’t make much sense outside of browsers.
Nonetheless, it’s possible to translate React Native primitives to the DOM language by using HTML tags — that (and more) is what React Native for Web does for us.
At this point, we have made sense of why it’s a good idea to use React Native as the common language for web and native. I am convinced it’s the way to go, but React Native for Web has been with us for a while, and it still struggles to spread, especially among web developers.
Using React Native for creating web apps isn’t simple, and not just because of the restrictions we need to fit it — it’s like native and web are still two separate worlds. Even if it’s already possible to use one codebase and run it everywhere, that code is full of conditions that can be run in one environment but not in another.
The same could be said of the libraries we can use to develop a React Native for Web app.
On the one hand, we have React Native libraries. We should be able to take these libraries and plug them into our React Native for Web project with no issue (unless they run native code or have native dependencies).
Unfortunately for our universal app, performance used to be the main focus among React Native developers — and we achieve the best UI performance in mobile when rendering is taken to the native side. In this way, we can make computations in the JavaScript thread without affecting the responsiveness of the interface. Those libraries with native code can’t be used in a React Native for Web project.
It would be great if, whenever possible, React Native library developers shipped their projects with a JavaScript alternative to their native functionality. If the native code doesn’t make much sense in a browser, React Native libraries should offer a mock of the native part that won’t break when it runs in a web environment.
Even when we find a React Native library that’s compatible with web, the process of making it work in our web app is not straightforward. In order to build our web apps, we use webpack as the bundler (more on this topic later), and it usually doesn’t transpile the files inside our node_modules
folder. React Native libraries don’t need to be bundled to work for mobile, so we need to add exceptions into our webpack’s module configuration in order to take them into the bundling.
If you are a React Native library developer, please 🙏, show some love for React Native for Web and ship a transpiled version in your libraries. Nowadays there are tools that make it really easy, like microbundle or bili.
On the other hand, we have React libraries, which are generally thought to work in browsers. They make use of HTML tags to structure the UI; thus, if we use them in our universal app, they will break the mobile version.
If you are a React library developer, and you think your library would make sense for mobile environments, you should know it’s possible to make it work in React Native as well by using the same primitives as React Native through react-primitives.
In the beginning, it’s a bit tedious to get in the flow, but when you get used to the primitives and Flexbox, it can even help improve the organization of your code. Moreover, you will be learning React Native, which is very handy to have in your tool belt.
Another pain we must suffer when creating a universal application is managing multiple bundlers. The standard method of developing and building apps in React Native is by using the Metro bundler. Made by Facebook, Metro allows us to build and test apps locally with almost no need for configuration. It’s shipped when you create a React Native application using Expo.
When we want to create the web version of our app, React Native for Web recommends using webpack as the bundler. Don’t get me wrong — webpack is great, but the need for two different build systems with two different types of configuration is a pain for my one head.
I hope in the future we can use just one bundler. It’s possible to use Metro to build our web app; I’ve been playing with using Metro to bundle my web app, and it looks totally possible. I could create a JavaScript bundle, but my web app didn’t really work because of some transpilation problems I just didn’t want to investigate. Any of you want to give it a try?
I’ve been talking about how React Native and ReactDOM developers can adapt their libraries to make them friendly with each other, and that should be just the first step.
Ideally, we would move toward unifying both worlds into a universal-react developers community. This is more than just adapting libraries not to break in any environment; rather, it’s creating tools that cover the needs of both worlds and add value to them.
As mentioned before, React Native for Web apps are really influenced by best practices for mobile. At the moment, when we create a React Native for Web app, we more or less adapt mobile apps to work in browsers. But do we really want a phone app, with its full-width layout elements and collapsible drawers, running in a big-screen desktop browser? Probably not.
That’s why the responsive layout revolution started in the mid-2000s: to make our designs adapt to different screen sizes. This is now a basic feature for any web project. In mobile apps, responsive UIs aren’t very common. But wouldn’t it be great to build apps that adapt to phones, tablets, and desktop without the need to code twice?
Responsive layouts are just one example of concepts from the web that can add value to mobile development. Another good one would be URLs. We don’t need to use URLs in our mobile apps, but the concept of assigning a unique identifier to our screens and direct access to some point is really powerful. This, too, is uncommon in mobile apps, which is why it’s rather difficult to handle URLs in React Native for Web apps when it should be pretty basic.
React Native for Web makes a great effort to take mobile goodies to web development, but there is not much in the other direction yet. In general, we should start thinking purely in terms of UI, no matter what platform we are addressing — and we are not at that point yet.
It’s hard to define hover interactions in React Native because when it was created, we thought they wouldn’t be necessary. For that same reason, gesture interactions in browsers are no piece of cake. All these cases should be covered with ease by a language that aims to be the universal approach to defining UIs.
Creating universal applications is a dream that came true, but like most things that are just starting out, there is still much to do to make it easy for everybody.
This is, as yet, a kind of unexplored world. As a library developer, I think it’s a great opportunity for us to build the next set of tools and libraries that will be used by the community of tomorrow. Wouldn’t you like to be the creator of the “next Redux”?
I want to make a special call to the Expo team to add support for React Native for Web to the Expo environment since I think they could play a major role in the transition. It would be a huge push for universal applications that the most famous development platform for mobile shipped web bundles out of the box.
Making Metro work for web would open the web development door for Expo (a huge community there), but educating React Native developers on mocking their native dependencies to work on the web will guarantee that your projects eject when you want them to. A win-win situation for everybody!
Definitely yes! Trying to run the same project across all platforms is certainly still challenging, and there are many gaps left to fill. But we can already use React Native as the one language to create the UI for different versions of our app, which reuse most of the same code even if they target different environments.
If you feel like helping solve some of the issues above, you will be pushing the dream of universal app development forward, and the whole community will be grateful to you.
If you just want to maximize your code reusability, set up a Lerna project, with mobile and web versions of your app as separate packages, and start creating your components using React Native. You will be reusing the whole UI, but you will be able to tackle platform-specific problems individually — no need to worry about compatibility.
If you are interested in this approach, I strongly recommend you read the article Building Cross-Platform Applications with a Universal Component Library from Lucas McGartland.
LogRocket is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.
LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.
Start proactively monitoring your React Native apps — try LogRocket for free.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowCreate a multi-lingual web application using Nuxt 3 and the Nuxt i18n and Nuxt i18n Micro modules.
Use CSS to style and manage disclosure widgets, which are the HTML `details` and `summary` elements.
React Native’s New Architecture offers significant performance advantages. In this article, you’ll explore synchronous and asynchronous rendering in React Native through practical use cases.
Build scalable admin dashboards with Filament and Laravel using Form Builder, Notifications, and Actions for clean, interactive panels.
8 Replies to "The state of React Native for Web"
Nice article. Microsoft have created ReactXP which provides an abstract layer over RN and ReactJS, I’ve just started using it and the documentation is a bit lean but it’s proving to be a pretty good experience so far.
https://github.com/microsoft/reactxp
Looks like your lerna link is broken. https://lerna.js.org/
@jake Fixed. Thanks!
Does logrocket work with React Native? Just pitched to boss. Boss says, gotta work for React Native too.
Thank you for sharing this article on react native application development. When it comes to app development react native is a great choice, as it offers app compatibility on both platforms Android as well as IOS
I used ReactXP for my last project. I wont say that its better than the react native but it totally depends on the choice of language and i selected Typescript for that project.
I was googled for react native blog and reached on your blog where I find best react native solution and information about react native. Thanks for sharing amazing react native blog.
I don’t like react-native-web at all. Let’s say I use TouchableOpacity on web, it does not have the hover effect. And I really don’t know how to create a hover effect with inline styles.