Common React Native gotchas and concepts that will help you before and during development ✨
React Native lets you use the same knowledge base of React and you can do native mobile app development. It is a lot of fun 🐼
If you are a React developer and know some basics of native development i.e. iOS 🍎 or Android 🤖 then you will pick up React Native easily i.e. not a noob 🙈. Although, it is not 1 - 1 relational. When I initially learned React Native, I forgot how my native development skills will be easily transferable.
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 basically 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. It makes your project pure JavaScript and you never have to dive into the native code.
Once you are ready to release it to the app/play store, you can basically “eject” which generates iOS and Android bundle/folders. (You cannot release without ejecting). During this process, things can break when something is being converted to native code. Not sure about you but this makes me very uncertain. I don’t like when there is a lot of magic going on ¯_(ツ)_/¯. It is usually very hard to debug the root cause of it.
➕ You should be building your projects and verifying it on a device at the end of every story/task you work on.
I would suggest using Expo when you are new so you can learn how everything works although 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 generates Android 🤖 and iOS 🍎 folders and files 📁 in your project right from the start which gives you so much visibility as a developer. There is no eject step as you get the project folders generated by default. You can do your builds right away and run it on a device provided your environments are up to date with the requirements. Unless you do something crazy this will work.✨
Layout components 💄
You 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 wrap the component usually 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. Hence, try not to hardcode values in too much as a
top: 5
will position differently for different device sizes.Phones can rotate and if that is a requirement for your app then you would need 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 if it feels like it, you are not coding for the browser 🕸 please keep this in mind at all times. While doing web development, your browser will provide the window object and you can easily access setTimeout 🕐 for example but there’s no native equivalent and you won’t know what happened.
Now, this might even work during a debug build where you might 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 web in mind while writing the package so again that might not work hence be careful before picking a package for your project. Look at their package dependencies too to make sure 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 once even if I close the app
You would want to use Async storage in this scenario. As user logs in using the login button, store the user info or token, 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.
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. Hence 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 expect to never open Android studio (IDE for Android) and Xcode (IDE for iOS) as you most likely will. The more familiar you get, the better it is for you.
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 only 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.
🍎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. I can’t think of an app without images 🤷.
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 hence 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
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 and has many ⭐. I found that it wasn’t good for beginners as it requires some native specific setup. I personally had a hard time setting it up even though I have native development experience. It also has a huge learning curve for a JS developer hence 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. When you need to test it on a device, you need a release build.
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 🚲 correspond correctly 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 so fetching data before component renders in componentDidMount and so on.
Although, how would you know if the app is in background or foreground (very native specific)? You get AppState from react-native which basically 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 how it corresponds to native development. 🙌
Please give it some 👏 if you liked it 🙏 and also share your React-native experience in comments 🙌