Are you a React developer who knows the basics of native development (i.e. iOS 🍎 or Android 🤖)? Then I bet you'll be able to pick up React Native easily aka you’re not a noob 🙈 What I mean by that is, you’ll be surprised while learning React Native how easily transferable your native development or React skills are. Don’t believe me? See for yourself.
Here is a list of React Native info and gotchas you will encounter as a React Native developer:
Getting a project together — Expo vs React Native CLI ✨
There are 2 main ways to get a react-native project together:
- Expo
- React Native CLI.
Expo is essentially an open source project built for newbies using Expo APIs to help build react-native and prototype apps quickly. You use the create-react-native-app to get started with Expo and it will make your project pure JavaScript so you never have to dive into the native code. Expo also has a tool called Snack 🍿which lets you run React Native projects in the browser. I like to use this tool to test something out quickly or try to reproduce a problem separate from my current environment. ✅
Once you’re ready to release it to the app/play store, you can use the Expo CLI tools to publish your app. During this process, things can break when being converted to native code. I'm not sure about you, but this makes me very uneasy. I don’t like when there is a lot of magic going on because it can be difficult to debug the root cause ¯\_(ツ)_/¯
➕You should be building your project and verifying it on a device at the end of every story/task you work on.
I would recommend using Expo while you’re still new so you can learn how everything works. Keep in mind that it’s risky while working with clients as debugging gets harder when something breaks.
For React-Native CLI, you create a full-stack project by using react-native-cli init. It will generate Android 🤖 and iOS 🍎 folders and files 📁 in your project right from the start which gives you a ton of visibility as a developer. There is no eject step as you get the project folders generated by default. This means you can do your builds right away and run it on a device, provided your environments are up to date with the requirements. ✨
Layout Components 💄
Use Flexbox flavour for laying out components on the page. If you don’t know Flexbox already, here is a great link 🔗to learn from. React-Native also provides native specific components such as Text, View, etc. You typically wrap the component in a View as View is designed to be nested inside other views and can have 0 to many children of any type.
➕Tip: Keep in mind that you are building for different devices so try not to hardcode values in too much as a `top: 5` will position differently depending on device sizes.
Phones can (and do) rotate so if that is a requirement for your app then you need to remember to account for both portrait and landscape mode while writing CSS. 💄
I also suggest using Styled-components 💅 for more of a design system.
You are not coding 🙅 for the browser 🕸
Even though it may feel like it, you are not coding for the browser 🕸 it’s important to keep that in mind. While doing web development, your browser will provide the window object and you can easily access setTimeout 🕐 as an example but there’s no native equivalent and you won’t know what happened.
This might even work during a debug build where you have hot reloading setup so browser might inject and it will look like it works. Although, it won’t on release builds as it does not have access to a lot of common web API’s. 🕸️
There are a lot of npm packages 📦 that keep the web in mind while writing the package. Since that might not work, be careful before choosing a package for your project. Also, be sure to look at their package dependencies so you can ensure you are good to go. Most libraries are very good at documenting it and a quick Google search will tell you the same, so do that first! 💯
Async Storage 🗑️
Android 🤖 and iOS 🍎 both have storage equivalents so you can store data on the device which gets deleted when you uninstall the app.
React Native provides a very helpful API called Async Storage which does a good job of storage on both platforms. Just like you would use local storage API in a browser, you use AsyncStorage in the same fashion.
On iOS, AsyncStorage is backed by native code that stores small values in a serialized dictionary and larger values in separate files. On Android, AsyncStorage will use either RocksDB or SQLite based on what is available.
User story example:
As a user 💁, I want to stay logged in after logging in only once, even if I close the app
You would want to use Async storage in this scenario. As a user logs in using the login button, store the user info or token. This way next time they come back to check if the token exists and hasn’t expired and accordingly show them your main screen or login screen so they don’t have to re-login.Please keep in mind that you don’t want to store any secrets in AsyncStorage such as password but might want to use Keychain in iOS and Keystore in Android.
Async await 🕐
Remember this is a native application. There is a UI thread that is responding to gestures from the user. Now with async await, the program can run other code like gesture responders and rendering methods while the async task is in progress. Therefore by using async await🕐, you can run your code concurrently🎉.
For example:
const storeUserInfo = async (token) => {
try {
await AsyncStorage.setItem("userToken", token);
} catch (error) {
console.log(error);
}
};
Don’t think you won’t open Xcode 🍎 or Android Studio 🤖
As a React Native developer, don’t think you’ll never have to open Android studio (IDE for Android) and Xcode (IDE for iOS) - you most likely will. The more familiar you are, the better.
User story example:
As a user 👩, I want the app to not rotate so that I have a better user experience.
From a developer perspective, this means you want to lock your device orientation to portrait mode. This is a setting that each platform has. You would have to make the change in androidManifest.xml for Android and a checkbox setting in iOS.
iOS config for locking orientation
🍎https://stackoverflow.com/a/32177887/1881309
🤖 https://stackoverflow.com/a/44485271/1881309
➕Tip: Always add “React Native” to your Google search, it will help you get better search results. 💯
Assets 📷
Assets are your images, audio and video files but the most common scenario is images. What's an app without images, right? 🤷.
User story example:
As a user 👵, I want to see the company’s logo in the login background
Since we are targeting different devices iOS 🍎 and Android 🤖, the resolution for each device is different, in light of that, my suggestion would be to provide 2x, 3x images. React Native does a good job of picking the right image based on different screen densities.
company-logo.png
company-logo@2x.png
company-logo@3x.png
For example, company-logo@2x.png will be used on an iPhone 7, while company-logo@3x.png will be used on an iPhone 7 Plus or a Nexus 5. If there is no image matching the screen density, the closest best option will be selected.
By taking this approach, your app will look beautiful💄and won’t pixelate.
Navigation
Navigation example (iOS)
React Native has tons of different libraries for React navigation. One of the most popular ones is react-native-navigation.
Even though the library is good ⭐, I found that it wasn’t great for beginners since it requires some native specific setup. Even personally I had a hard time setting it despite having native development experience. It also has a big learning curve for a JS developer and so I would recommend using https://reactnavigation.org/. This library took me 5mins ⏲ to get started and is very easy to use.
Debug vs Release builds 🚀
Debug builds are mainly for development and Release is for production i.e. App store 🍎 and Play store 🤖 deployment. During development, you are running a debug build where you have hot re-loading 🔥 and the ability to debug remotely. For a release build, you won’t have access to a browser debugging environment. That means when you need to test it on a device, you should generate a release build to make sure your app will work on a native device.
When you want to run the app on your device in a non-dev environment, you need to run the following command that generates a release build for you Let’s take a look at an iOS example:
node node_modules/react-native/local-cli/cli.js run-ios --configuration=Release
How App lifecycle corresponds to component lifecycle 🚲
The React component lifecycle 🚲 corresponds directly to the Activity lifecycle in Android or Screen in iOS. As you usually build your React apps, you would do the same for React Native by fetching data before component renders in componentDidMount and so on.
But how would you know if the app is in the background or foreground(very native specific)? You get AppState from react-native which has event listeners and you can listen to it as the app goes in background or foreground. Here is some sample code:
import { AppState } from 'react-native';
class App extends Component {
componentDidMount(): void {
AppState.addEventListener("change", this._handleAppStateChange);
}
componentWillUnmount(): void {
AppState.addEventListener("change", this._handleAppStateChange);
}
// state can be active for foreground and inactive when transitioning between background and foreground
_handleAppStateChange = (nextAppState) => {
if (nextAppState === 'background') {
console.log('App is in background!')
}
}}
Hope you found this post useful 💯 and it gives you a good understanding of how React Native works and corresponds to native development. 🙌