# React Native Guidelines (Part 1)

Each year, mobile app development gets more complicated but the fundamentals stay the same. This guide provides an overview of good open-source libraries and tools we use. It will help you to get your app up and running. We will also look into the fundamentals of the mobile environment and how to set it up.

- URL: https://sudolabs.com/insights/react-native-guidelines-part-1
- Published: 2022-02-25
- Updated: 2024-01-16
- Author: Tomas Varga, Senior Engineer
- Categories: Tech
- Language: English

_React Native_ (RN) is a popular **framework for creating cross-platform applications** with React-like syntax. In our four-year journey at _Sudolabs_, we have created and deployed a lot of them. As the framework matured, we refined our process of working with it on mobile platforms (iOS, Android) to **deliver the best customer experience**.

Each year, mobile app development gets more complicated but the fundamentals stay the same. This guide provides an overview of good open-source **libraries and tools we use**. It will help you to get your app up and running. We will also look into the fundamentals of the mobile environment and how to set it up.

## Prerequisites

Let's take a look at all the software we will need to develop a _React Native_ application for _iOS_ and _Android_.

- **Android development**

  - [Android Studio](https://developer.android.com/studio)
- **iOS development (macOS)**

  - [Xcode](https://developer.apple.com/xcode/resources/)
  - [Cocoapods](https://cocoapods.org) - Manages library dependencies for the Xcode project. From React-native v60+ it's required in each React Native project.
- **General prerequisites**

  - `npm`/`yarn`

    - As with every Javascript project, we're going to need a package manager to handle our dependencies.
  - `nvm`

    - It's not a requirement, but `nvm` is a great tool (when working in a team of developers) that will make sure to lock a specific node version for our project.
  - `react-native-cli`, Node, Watchman, and JDK ([React Native Getting Started Guide](https://reactnative.dev/docs/getting-started))

## How to open the project from Xcode or Android Studio

You might be thinking, why are you guys telling me how to open a project? It's important to open the correct file because if you don't do it right, you can run into issues with libraries not being linked correctly.

### Xcode

1. Open Xcode and you should see a window with your projects.
2. Click on **Open another project...** and go to **mobile-client/ios** folder.
3. Click on **ProjectName.xcworkspace** and confirm it with **Open**.

Note: Make sure it's a file with the `.xcworkspace` extension. Otherwise, the build can fail with multiple errors.

### Android Studio

1. Open Android Studio and you should see a window with your projects.
2. Click on **Import project (Gradle, Eclipse ADT. )**.
3. Go to **mobile-client/android** and confirm it with **Open**.

## Absolute imports

Absolute imports are handled with [Babel](http://babeljs.io) plugin [babel-plugin-module-resolver](https://github.com/tleunen/babel-plugin-module-resolver). Thanks to this plugin, we can change absolute imports from this:

```
import MyUtilFn from "../../../../utils/MyUtilFn";
```

Into this:

```
import MyUtilFn from "utils/MyUtilFn";
```

In order for absolute imports to work in React Native, we need to define `root` as our `src` folder, then we don't need to add aliases for each folder separately. Custom babel configuration needs to be specified in `babel.config.js` or `.babelrc` file like this:

```
module.exports = {
  presets: ["module:metro-react-native-babel-preset"],
  plugins: [
    [
      "module-resolver",
      {
        root: ["./src/"],
        alias: {
          theme: "./theme.js",
        },
      },
    ],
  ],
};
```

### App Icons

> Every app needs a beautiful and memorable icon that attracts attention in the App Store and stands out on the Home screen. \[...\]

-- https://developer.apple.com/design/human-interface-guidelines/ios/icons-and-images/app-icon/

⚠️ Graphical requirements:

- The image has to be square.
- Don't use a transparent image.
- Minimum size of the image is 1024x1024.
- Formats accepted: png and jpeg.

To generate app icons we recommend this tool from @bamlab [react-native-make](https://github.com/bamlab/react-native-make). It will simplify the manual labor.

### Launch screen

> The launch screen is a user’s first experience of your app.

-- https://material.io/design/communication/launch-screen.html

The launch screen is another important part of your application and a way to transition users to your application seamlessly. It can help you decrease the perceived loading time and improve the user experience.
To generate a static launch screen, you can use this library — [react-native-bootsplash](https://github.com/zoontek/react-native-bootsplash)

#### ⚠️ Recommendation

We are **NOT** recommending to install [react-native-splash-screen](https://github.com/crazycodeboy/react-native-splash-screen) due to various issues with third-party libraries, e.g. Firebase. You can read more about the differences [here](https://github.com/zoontek/react-native-bootsplash#%EF%B8%8F%EF%B8%8F-comparison-with-react-native-splash-screen).

### Setup for multiple environments

Why do we need to have an app with **multiple environments**? There are a lot of good reasons. The most important one for us is to have a separate environment for third-party services such as monitoring, analytics, or authentication. This way we can analyze data correctly without the noise from development.

**Schemes or build variants** are similar to environments but for mobile apps. They help us distinguish between development, staging, production, or any other environment. To build the app with different settings, iOS uses schemes and configurations while Android uses variants.

A `react-native` project comes with two configurations for iOS and two build variants for Android — `debug` and `release`.

When we want to launch or set it up with custom settings we can run into issues; don't worry, we have solutions for these.

#### Schemes and Build configurations (iOS)

In a React Native project, the default scheme is the name of the project `project-name.xcscheme`. Based on the build configuration included in the scheme's actions such as run, archive, test, and analyze; _Xcode_ will determine what build settings should be included.

The build configuration has different settings for app names, deployment keys, API keys, and bundleId. You can reuse the configuration with schemes or create a new configuration for each scheme. The latter is part of our process and something we recommend.

As we mentioned earlier, a good example is third-party services. If the project has multiple analytic apps, each configuration can be configured for a different app. To send the data to the correct app, you need to run a different scheme configured to a build configuration with a specific app id.

#### Variants and Build types (Android)

Build variants represent a combination of different settings and can be a different version of your app. For example, you can have a variant for your demo or a free version of your app. Variants are not configured directly, instead, we are using build types.

#### ⚠️ Known issue

In the older version of `react-native-cli`, you might have had a problem if you renamed your scheme to a different name. This could happen because `react-native-cli` had a default scheme set to the name of the project. This was fixed in `4.13.0`. You can find more about this here->[Build fails to install when using the iOS 14 SDK](https://github.com/react-native-community/cli/issues/1208). If you are stuck on an older project, just install `react-native-cli` to your dev dependencies (`npm i react-native-cli --save-dev`).

## App environments

Each project will have different requirements to meet but the following solution can be extended to suit your case.

![](https://a.storyblok.com/f/117609/1152x675/757492a9d5/app_environments.png)

**ProjectName** scheme is used for the development part. Other schemes, e.g. `develop` or `production`, are used for the deployment and testing. Developers can switch between schemes as a way to replicate a bug on local machines or devices.

### How to create a new scheme and a new configuration?

#### iOS

##### New scheme

1. Open Xcode with your project. Go to Product->Scheme->Manage scheme.
2. Click on the `ProjectName` scheme and then on the small gear icon.
3. Click on `Duplicate`. Make sure that your new scheme has the `shared` checkbox checked. Otherwise, the scheme will not be accessible for other team members from a source code repository.

##### New configuration

1. Click on the blue icon with `projectName` at the top of the file tree view. You should see the Project and Targets on the left.
2. Click on the PROJECT->`projectName`. There should be 2 basic configurations - Debug and Release. We will make a third one — `Develop`.
3. Click on the `+` icon and choose `Duplicate "Release" configuration`. Rename the configuration to "Develop".

##### Connecting a scheme with the new configuration

1. Go to the Develop scheme from Manage scheme->Develop->Edit scheme, or directly from Product->Schemes->Edit scheme. Make sure to choose the correct scheme.
2. Change every build configuration from Debug or Release to Develop.

Note: The important tabs here are the `Archive` tab for the deployment of our builds and the `Run` tab for our development.

#### Android

1. Go to `android/app/build.gradle` (not to be confused with android/build.gradle) and define a new build type inside the file.

```
 buildTypes {
        debug {
            applicationIdSuffix ".debug"
            versionNameSuffix '-DEBUG'
            resValue "string", "CodePushDeploymentKey", '""'
            resValue "string", "app_name", "ProjectName-DEBUG"
        }
        releaseDevelop {
            versionNameSuffix '-DEVELOP'
            applicationIdSuffix ".develop"
            minifyEnabled enableProguardInReleaseBuilds
            matchingFallbacks = ['release']
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
            resValue "string", "app_name", "ProjectName-DEVELOP"
        }
        release {
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
            resValue "string", "app_name", "ProjectName"
        }
    }
```

As we mentioned earlier, this will create a different application due to a change in applicationId. For example, a new build type called `releaseDevelop` will have _applicationID_ `com.project.name.develop` instead of `com.project.name`.

By setting `matchingFallbacks` to `release`, all dependencies will match the same build type. This way we can overcome errors where build type `releaseDevelop` cannot be found in third-party libraries.

```
Error:Failed to resolve: Could not resolve project :mylibrary.
Required by:
project :app
```

We are changing the app name in the build type. For this to work, we need to go to the `main/AndroidManifest.xml` and have this line `android:label="ProjectName"` set to `android:label="@string/app_name"`.

To run your android app after the changes go to `package.json` and change the following line `"android": "react-native run-android"` to `"android": "react-native run-android --appId com.project.name.debug"`.

### How to launch a different environment?

There are two ways for switching schemes — either from the command line or directly from Xcode / Android Studio.

1. Command line

- iOS: `react-native run-ios --scheme iOSSchemeName --configuration iOSConfiguration`

  - example: `react-native run-ios --scheme Develop --configuration Develop`
- Android: `react-native run-android --variant AndroidSchemeName`

  - example: `react-native run-android --variant releaseDevelop`

1. Xcode

   - You can find the scheme selection next to the \[>\] run button and \[ \] stop button. Choose a scheme that you want the app to launch with and don't forget to choose the correct device/simulator.
2. Android Studio

   - Go to **Build** > **Select Build Variant** and select one from the drop-down menu. Then locate \[>\] run button and press it.

### Takeaways

In the first part of the React Native guidelines, we have taken a look at the basic setup for a React Native project used at Sudolabs. We have walked through opening a new project, creating app icons and launch screens, and learned how to handle multiple environments.

In the next part, we will take a look at the **app signing and deploying process.**
