React Native enables developers to write code in React that can be compiled to both Android and iOS native code, eliminating the need to manage two separate codebases. But what if you also want your React Native app to work on the web?
Enter React Native for Web.
How it works
React in its original form is used to build web applications. Its building blocks consist of HTML5 elements like div and span. React Native, on the other hand, uses custom APIs like View and Text, which in turn are compiled to mobile OS-specific UI APIs. This difference is (one of the reasons) why we have different codebases for web and native apps.
React Native for Web takes the custom React Native APIs like View and converts them to HTML5 counterparts like div. By just using the React Native APIs, we can build for Android, iOS, and web.
Who should use it
React Native for Web is a good option for those who are starting with a native app, and want to turn that native app into a web app very quickly. It’s also a good option if the web app and the natvie app are to be very similar: in other words, the web app should do everything the native app does, and no more.
React Native for Web is a poor option for those who are trying to build fundamentally different functionality into their web apps from their mobile / native apps.
If React Native for Web sounds too good to be true to you, you’re not entirely wrong; like any framework it currently has a number of specific limitations. These include:
1. Limited web API support
Not all APIs that are available in React Native are available in React Native for Web. This means you may have to re-implement the functionality or simply not support it at all when on the web. An example of this is the Image Editor. Another example is mobile hardware APIs that are not accessible to the browser (e.g. the accelerometer).
2. Missing core components
Not all core components available in React Native are available with React Native Web. An example of this is RefreshControl. Sometimes a third party developer will create a separate, web version of the component, for example React Native Web Refresh Control, that you can use.
3. Styling issues
In terms of styling, React Native for Web inherits all the disadvantages of React Native. In particular, styling in React Native is very limited. Among the missing capabilities are:
- Styling child components
- Selecting sibling elements
- Using pseudo-classes like :hover or :focus
This is because unlike React, which uses HTML and CSS, React Native uses a separate layout engine called Yoga. If you need access to advanced styling, you may find React Native for Web to be limiting.
A number of popular React Native libraries do not have proper support in React Native for Web, for example React Native Google Autocomplete.
If React Native Web isn’t a good fit for the reasons above, there are a few alternatives:
- Solito is a cross-platform project that focuses on navigation. Navigation is often the hardest piece of sharing code across platforms, because the web has plain URLs for navigation state while apps have nested navigation patterns. Solito provides a light wrapper around React Navigation and Next.js that lets you share navigation code across platforms.
- If you don’t want to rely on wrappers or converters, you can also build a cross-platform component library that compiles to 2 npm modules, one for web and one for mobile, then import them into your respective web and mobile codebases.
Having said all of this, React Native for Web is great and super popular, so hopefully it fits your use case. The next section will run through how to get it up and running for your application.
There are several options for adding React Native for Web to your React Native Apps:
Option #1: Use Expo
Expo is an open source toolchain built on top of React Native. Its main components are:
- Expo CLI, a cli for creating React Native projects, viewing logs, publishing, etc.
- Expo client, a mobile app on your phone that lets you try out your apps without having to go through an emulator or XCode.
Expo comes with web support by default, and is the recommended way of using React Native for Web. If you are starting a project from scratch and would like to run it on iOS, Android, and web, follow option 1.1 below. If, however, you already have an existing React Native (non-Expo) project and would like to move it to Expo, follow option 1.2.
Option #1.1: Use Expo to get started from scratch
- Follow the instructions here to install the Expo CLI and download the Expo Go app on your iPhone and Android phone.
- Follow the instructions here to create a new app and start the development server.
expo start, you will have the option of opening the web app by pressing
w, or opening the iOS app by taking your phone and scanning the QR code printed in the terminal.
Option #1.2: Migrating an existing React Native project to Expo
If you have an existing React Native project that you would like to migrate to Expo, your best bet is to:
- Create a new project with
expo init– choose blank or blank (TypeScript).
- Copy over your source code and get it to a working state piece-by-piece.
- Add your dependencies to the package.json.
However, before doing the above, you should make sure that your existing codebase qualifies as easy to migrate. In particular, you should check the following:
- Whether you are using any custom React Native code in your app. If so, can it be replaced by something from the Expo SDK? If not, you may not be able to use Expo. Proceed to Option #2.
- Whether you are using any dependencies that are NOT on this exhaustive list of libraries in the Expo SDK. If you are, you may not be able to use Expo. Proceed to Option #2.
Option #2: Add React Native for Web to an existing React Native app using Create React App
The instructions below assume that you have installed all the React Native development environment requirements. If you have not done so, please follow the instructions here.
1. Create a React Native project:
npx react-native init DemoProject cd DemoProject
Create the necessary files and folders:
mkdir src mkdir public touch public/index.html mv App.js src mv app.json src cp index.js src mv index.js index.native.js
Install dependencies for React Native for Web:
yarn add react-dom react-native-web yarn add --dev react-scripts
2. Add the following snippets to the corresponding files:
Edit package.json and add the following line to the scripts section:
"web": "react-scripts start"
3. Execute the following command to run the application on all 3 platforms:
yarn ios && yarn android && yarn web
Option #3: Manual Setup with Custom Webpack Configuration
To add React Native for Web to an existing React Native project with a custom webpack configuration, follow this guide.
Option #4: Build an app with Retool Mobile and publish as a PWA
Retool Mobile is a new option that allows you to build and access your mobile apps natively on Android, iOS, as well as on the web out of the box by deploying the app as a PWA. Here is a quickstart guide for app building. Once your app is complete, click on the “Share” button on the top right of the editor. Copy the “share viewer link” link. This link will display your app as a PWA with no additional work.
We’ve presented several options for making your React Native apps work on the web using React Native for Web – making it possible to build both a web app and a mobile app from a single codebase.