It’s been around 5 months since I started learning React Native with Typescript. Here are some tips, tricks & resources that I’ve gathered along the way which may help you on the following topics:
- Project Templates
- Local Storage, SVG, Accessibility, Testing
- Screen Sharing
- Debugging
This quick guide is intended for people who have some basic knowledge of React & React Native, and does not cover React concepts.
💡 Remember to use the table of contents to jump anywhere to areas of interest.
Project Templates
Using templates can greatly accelerate your development speed and also these templates tend to follow best practices.
If you are new to React Native, start with the minimum
If you are new to React Native, at the RN official documentation, you are given 2 choices: to create a project with Expo, or bare React Native. Both works well, it’s just that what they support differs. Here's my quick take on the main appeals of each workflow.
- Builds made with Expo are much more faster.
- Expo has a Snack playground where you can upload your React Native project for sharing your app to the public easily. Example of a snack for Sencha Teahouse, a React Native app I made for learning
- Expo recently released EAS for building & releasing the app to production conveniently.
- While the bare workflow may not have these benefits, what it offers is much more customisation in terms of the packages you can use (not all open source libraries support Expo). This is a big deal breaker for some apps, so apps made with the bare workflow are still prevalent.
You can also refer to this documentation on the limitations of Expo written by Expo team.
Now that you understand the high level overview of the 2 workflows, here are the respective basic templates you can use to create React Native apps.
- Expo-cli’s blank templates
- React Native Community’s Typescript template
If you ever change your mind after creating a bare RN project, you can refer to the official documentation by Expo for installing Expo modules to do so.
If you are more familiar and prefer to fly faster
If you are more familiar with React Native, you might want a more comprehensive boilerplate that has features such as state management, navigation, themes etc already set up so you can spend more time on implementing other features of interest. Here are some of such templates.
- Kitten Tricks template, a starter kit app based on the UI Kitten library with Light and Dark themes support.
- TheCodingMachine’s React Native Boilerplate, a template built with an architecture based on Separation of Concerns. Comes with support for redux, react-navigation, flipper, prettier, eslint & i18next.
- Ignite template, a template that offers similar features as TheCodingMachine, but for state management, they use MobX instead of redux. This template also supports Expo. Something even cooler is that it comes with its own generators for components, screens and MobX models.
Local Storage
Learning to design & manage your local app data is especially important on mobile apps given how users are met with internet problems more frequently as compared to web apps. On the web, there's local session and cookies for storing local browser data. For React Native, to store local data for your app, you can choose a library from the list below.
Libraries for local storage on React Native
- Async storage → the standard de facto basic key/value storage used on React Native
- React Native MMKV → claims to be the fastest key/value storage for React Native (~30x faster than Async Storage), implemented based on the mobile key-value storage framework developed by WeChat. It also supports encryption. You can check out Billy, a bill tracker app where I used this framework.
- React Native Keychain → a recommended way to add user credential storage to React Native
SVG
SVG is the de facto standard for pictures that scale on different device resolutions on web apps. On mobile apps, this is also mostly the case especially for icons, but there may be rendering & performance issues for more complicated SVG.
In the case you have determined that you want to add icons/ SVGs, these are the common libraries for adding SVG to React Native.
- Custom SVG file or via URL: react-native-svg
- Bundled Icon Sets e.g. AntDesign etc: react-native-vector-icons
Important note: Regular SVG is constructed differently from React Native SVG component. You can use SVGOMG for file size optimization and transform to convert your SVGs.
Custom Fonts & App Icon
Aside from adding media in the form of SVGs to your app, having custom fonts & app icon can help you to establish a unique branding of your app. You can check out this tutorial article that I have written previously on how to add custom assets in React Native
Accessibility
Larene has compiled a great list of mobile accessibility resources for Creating Inclusive Apps with React Native.
Testing
Here’s a guide to React Native Testing library by one of the Hashnode’s React Native developers, Shad! It also has additional instructions for expo projects.
For E2E Testing, you can use Detox.
Screen Mirroring
After you have completed certain features, you might wanna demo how your app works. With how common virtual meetings are nowadays, If you want to show app interactions on your physical mobile device via Zoom etc, here’s some open source software to help you.
- scrcpy (pronounced "screen copy")
- Compatible with most OS (Windows, Mac, Linux)
- Provides display and control of Android devices connected via USB or over TCP/IP. It does not require any root access.
- Other cool features: recording, copy paste in both directions
- Vysor
- Compatible with most OS (Windows, Mac, Linux)
- Provides display and control of iOS & androids app via the Vysor software on your desktop
- Other cool features: Audio mirroring, Vysor can be embedded into other websites via iframe
Troubleshooting
While developing your mobile applications with React Native, you will inevitably encounter certain common problems. First of all, get a debugger.
There are 2 debugging applications that I’ve used before for debugging RN apps, each with their pros and cons:
My preferred tool is Flipper because of the community supported plugins available for it — I have used it to navigate React component trees with React Dev Tools, as well as Zustand state, Async Storage, MMKV & so on!
⚠️ Caveat: Requires React Native v0.62
This requires a slightly more complicated set up as you need to install the relevant plugin dependencies in your project itself, but it could potentially help to improve your local development process vastly.
For more information on this, you can watch the talk that I have given previously on Debugging Mobile Apps with Flipper.
Resolving Problems that cannot be debugged
By problems that 'cannot be debugged', I meant that problems that may not have logs in the debugger or make much sense on their own. More often than not, these problems are build problems, and cannot be traced just by using the debugger. Below are some common ways to fix those problems.
Clean your cache
Sometimes your installation of dependencies may get corrupted as you add or update dependencies, and your application will throw strange errors. A simple thing to try is to reset your cache.
npm start -- --reset-cache
Otherwise, remove your node modules and then reset your cache.
rm -rf node_modules
npm start -- --reset-cache
If the above is not enough, you can do the full clean method that is shared by Florian Marcu, by adding the method
watchman watch-del-all && killall -9 node && rm -rf yarn.lock package-lock.json node_modules ios/Pods ios/Podfile.lock android/app/build && npm install && cd ios && pod update && cd .. && npm start -- --reset-cache
iOS Problems
Require a higher minimum deployment target
Such errors might occur if you try to use an outdated template / newer dependencies.
Specs satisfying the `React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`)` dependency were found, but they required a higher minimum deployment target.
To resolve these, go to your ios/Podfile
and update the deployment target to
platform :ios, '11.0'
Of course, be sure to check with your team & biz if it is ok to proceed with this!
Android Problems
spawn./gradlew error EACESS
This may be an error that you might encounter while trying to install the app to an android device
error Failed to install the app. Make sure you have the Android development environment set up: https://reactnative.dev/docs/environment-setup.
Error: spawn ./gradlew EACCES
at Process.ChildProcess._handle.onexit (node:internal/child_process:282:19)
at onErrorNT (node:internal/child_process:477:16)
at processTicksAndRejections (node:internal/process/task_queues:83:21)
To fix it, change the privileges on the Gradle wrapper file.
chmod 755 android/gradlew
Corrupted Android build
If you’re interested, here’s a scenario for how you may encounter an android corrupted build. There are times where initially you could install the app successfully on android, but then somehow after adding a new package that seems to be incompatible with the previous packages, it fails to install. Afterwards, even if you did remove the incompatible package, you might still be getting the same errors and unable to build on an android device.
If you ever get a corrupted build, there are a few things you can try.
First, it might come from a corrupted build folder cache, so you can try to clean the build.
./gradlew clean
If cleaning doesn’t help, then it may be due to corrupted daemon, so you can try stopping all daemons.
./gradlew --stop
Alternatively, if you’re on MacOS, you can also remove them directly as such. I’m not sure of the path for windows.
/home/username/.gradle/daemons
Then, you can also see the status of your daemons with this command
gradle --status
Generating UUIDs
The most common way to generate UUID in web apps is to use the uuid library, however this has a caveat if you include it in a React Native project. When I added the UUID library to my app, the iOS app worked fine, but it causes the android app to crash. There’s a reported issue on this and a user chinomnsoawazie helped to provide a solution to this.
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';
You have to install react-native-get-random-values
library, run npx pod-install
to make sure that the iOS app dependency is linked, and then import it before uuid. Now your app should work for both android and iOS.
That's a wrap folks! 🎉
Thank you for reading, hope you enjoyed the article!
If you find the article awesome, hit the reactions 🧡 and share it 🐦~
To stay updated whenever I post new stuff, follow me on Twitter.
Recently Hashnode introduced a feature for Sponsors ✨ You can buy a cup of tea for me over there if you like!