Being free from “expo” in React Native apps
--
Expo allows you to work using an SDK with access to native functionalities easily saving your time whether you desire to create an app in few steps.
The last versions of React Native already come with expo introduced.
What’s the easiest way to remotely share a mobile app that’s still under development without Expo?
This article covers a way to develop without expo for people who decided to keep the project according to their own development strategy.
If you want to share your project in real time, please search about Codeanywhere IDE.
You can also share pieces or the entire React Native code by Codesandbox.
See below an embed code as example:
You can also read about that here:
Expo works fine for me.. So, why would I get rid of the expo?
I made a list with some situations you don’t need expo in your life:
- to customize the installation;
- to install custom version of modules (oldest/latest);
- to use your own React Native modules;
- to avoid inconsistencies in modules developed by the community;
- to have more control of project dependencies;
- to use new ReactJS features;
- to use your own CI/CD implementation;
First we are showing you how to create a project with expo
Basically you need create-react-native-app
.
We’re going to build an app using the commandcreate-react-native-app RNwithExpo
. It’ll install everything for you and will run the project pretty easy.
Basically, React Native project using expo has this little structure:
It because expo controls all for you. NOT you!
But.. We’d like to have control of the development of our applications.
Now we are going to use two ways to create our project without expo.
Using the react-native-cli
command line
The Facebook community developed a way to build React Native applications without expo. You can read more about that below:
Basically, we install a react-native-cli
and build a blank/tabs project using the command init
, such asreact-native-cli init RNwithoutExpo
, where RNwithoutExpo
is the name of the project we want to create.
This project is using the last compatible dependencies between React and React Native. It’s also using babel
as JavaScript compiler and jest
as JavaScript testing.
Running it we’ll see all OK in our project without expo.
Ejecting your React Native expo project
Scenario: You are in a situation where your MVP has been approved and you’re seeing in your research on the development strategy, that the application will grow fast, and you need to install many features and testing them as soon as possible to choose the better to your product life cycle.
If you are in this scenario, you want to eject expo of your application and try to work with your own npm packages. You can eject expo running the command npm run eject
on the console.
Make sure you’ll choose the option React Native: I’d like a regular React Native project and then rename your project accordingly.
You’ll see a few questions on the console about the ejecting task:
- How would you like to eject your app? React Native
- What should your app appear as on a user’s home screen? React Native App
- What should your Android Studio and Xcode projects be called? ReactNativeApp
Where React Native
is the name of your app. Change it to your preference.
Soon after ejecting expo you’ll receive your project like this:
So I’ve discovered it’s not enough for you to eject expo to be independent of it. You need to do some adjustments in your project, and that’s what I’ll show you below.
First, you’ll start with the package.json
file.
You need to remove any reference of expo
of your packages.
After that, remove .expo/
directory, and remove the babel-preset-expo
on the babel.config.js
file. If you prefer, you can simplify the babel.config.js
configuration.
In this step, many developers make the mistake updating React to the last version. This way the application will not run.
In this article, I’m not taking into account settings for iOS environment.
The most common error involving Gradle is:
Could not get unknown property 'mergeResourcesProvider' for object of type com.android.build.gradle.internal.api.ApplicationVariantImpl.
But I have the solution to that!
Return React to an earlier version. See the package.json
file below:
{
"scripts": {
"start": "react-native start",
"android": "react-native run-android",
"ios": "react-native run-ios"
},
"dependencies": {
"react": "^16.8.3",
"react-native": "^0.59.1"
},
"devDependencies": {},
"private": true
}
In the previousandroid/build.gradle
build configuration:
…change some things in the buildscript
property:
An observation: We wont use SDK version 28 (Android 8) to targetSdkVersion
property to avoid unnecessary configurations. But if you want, below I present a link teaching how to fix the most common error about this version:
So, let’s continuing.. Now change the version of distributionUrl
in the android/gradle/wrapper/gradle-wrapper.properties
file.
So far you didn’t have to install anything
…other than compatible versions of React and React Native. And also you just made a few adjustments to gradle config files.
We are missing to create an important file
We are almost missing to create the index.js
file inside our application. :D
Here’s an example of code to the /path-to-project/index.js
file.
import { AppRegistry } from "react-native";
import App from "./App";
import { name as appName } from "./app.json";
AppRegistry.registerComponent(appName, () => App);
If you have any issues related to Remote JS Debugging, follow the steps below:
Metro Remote JS Debugging
Now we don’t have any JavaScript debug for our expo ejected application.
This error is very easy to be remedied because it’s very easy to be identified as well.
Error: listen EADDRINUSE :::8081
at Server.setupListenHandle [as _listen2] (net.js:1345:14)
at listenInCluster (net.js:1386:12)
at Server.listen (net.js:1474:7)
at Promise (/home/paneladm/projects/react-native-apps/RNwithExpo/node_modules/metro/src/index.js:253:20)
So we need to install metro-react-native-babel-preset
package as devDependencies
npm i -D metro-react-native-babel-preset
and mention it in the babel.config.js
file, something like this:
presets: ["module:metro-react-native-babel-preset"]
I added an extra Text
line followed by some style to test the Live Reload and all OK now.
That’s it! =)
Now you have the control over your project!
I created a github repository about the project worked on this article.
Unable to load script from assets index.android.bundle
If you have any problems with the Android bundle it’s because the assets
folder doesn’t exist. To solve that issue, follow the instructions at this link:
I hope I’ve helped those with doubts on how to create applications in the new versions of React Native without using these magic libs.
Any question, don’t hesitate to ask me.