18
What I Learned as a Web Dev on My First React Native Project
What was your first year like when you started your coding career? I remember it went quite smoothly for me, and I jumped onto a project pretty early on. It was an ongoing project—so time to market wasn't a key factor—and I got great support from my colleagues. But let's face it: With older projects, you mostly deal with bugs, optimizations and continued refactoring, plus some features here and there.
Refactoring did actually keep my motivations high by opening up a path for learning how to write better code. Yet as a junior dev, it is essential to try new things to get a greater perspective; that's what helps you answer questions about your career, coding preferences or favorite libraries—which is the core of most fun arguments with your colleagues.
Therefore, when I hit one year in my coding career, it was a proper challenge and blessing in one when a new project came around—specifically a React Native (RN) project. Just like that, together with my senior colleague, I started building a new mobile app for iOS and Android using my web development skills. Meaning that my previous article should be renamed to How I Left a Financial Markets Career for Web Frontend Development. And, as in the previous article, this experience has come with plenty of lessons worth sharing.
While the React Native coding environment feels quite familiar to a React developer, you actually lack the knowledge of what you are able to build with your skills. Here is where the afore-mentioned greater perspective comes into play; as a developer, you need to broaden your horizons—otherwise, you are risking living in your small bubble, fearing change and getting stuck.
Perpetually finding myself in somewhat of a "code newbie" mindset, I know that there are certain gaps in my coding skills that I need to fill.
I always prefer learning by actually seeing someone building something. At the time of this project, my favorite tutor, Mosh Hamedani, had released his React Native course (free YouTube preview), so I signed up for it and built my first app. Besides the app building and his coding tips, the great thing about Mosh's course is that he walks you through the setup of Xcode and Android Studio, which are needed for using mobile device emulators/simulators. You want to get this right. But do not worry, we can still write our code in, for example, VSCode.
Another great tutor, The Net Ninja, has a free course also worth checking out. And finally, I've discovered William Candillon, who is a big guru in the React Native community especially thanks to his "Can it be done in React Native?" YouTube series. While William is mostly focused on animations, around that time he also started a series called "React Native Fashion", where he builds an app from scratch based on designs in Figma—which is very close to the real developer experience, so check it out!
You will find that almost all tutorials, be it the ones from YouTube or Medium, will use Expo, a framework and set of tools for building React Native applications. Its "managed" workflow prevents and eases many headaches React Native developers face. Expo apps are super easy to set up and are made available on your mobile device through a simple Expo client, meaning it skips the App Store and Play Store in the process. This is obviously a great choice for a tutorial or an MVP, but is it good for a professionally built app?
For now, it usually isn't! Expo does not allow you to touch native Android and iOS modules and, in general, you are locked to their environment — which is very powerful, but the situation is still not ideal. If you'd need something that is not available in Expo, you would have to go through a potentially painful ejecting process. Also worth mentioning is that Expo apps are significantly bigger in size. At STRV, we always use React Native CLI to build apps so that we can provide the best value for our clients' money.
Many tutors and commentators heavily promote Expo and scare new developers by claiming that with React Native CLI, devs will have to touch native iOS and Android modules to get things working. But in reality, those are big scares of the past. Since React Native version 0.60, almost all libraries are auto-linked and you just have to install them with npm or yarn. I imagine that before that time, it was probably a huge headache; but now, already close to version 0.64, things are much better. Though, yes, there are cases when you have to play around with native modules—for example, to set up a splash screen and an app icon—but, again, you are a developer and, sometimes, you need to get your hands dirty. Avoiding difficult things may just create internal anxiety that will surface later.
It is different. Once you set up your Android Emulator and iOS Simulator, you can start exploring your code changes—and will soon discover that not everything is as simple as it is in tutorials.
As a web dev, you check how your app behaves across various internet browsers. In mobile development, you check if things are working in the same way on both Android and iOS. This is important. There are some libraries or component properties that are platform-specific only. Documentation is your friend, so keep it in mind. It can literally be trivial things—like shadow properties that have no effect on Android, because you'll have to utilize preset elevation properties.
Another parallel is checking for website responsiveness while resizing the browser screen versus checking how your app looks on mobile devices with various screen sizes and pixel density. This can easily lead to misaligned design. If your simulator is big enough and fits all things on one screen, it may require a ScrollView component on a smaller device to allow users to reach all the offscreen content.
There are many ways to debug your app by reaching for tools like React Dev Tools, a simple element inspector or a network tab that you're used to. Tools such as React Native Debugger are also quite popular, but they require turning on the 'Remote debugging' mode on your simulator, which I found sometimes interferes with the app and throws weird errors.
With React Native version 0.62 comes Flipper, Facebook's own debugging tool included as a default for you to use. This is great because it works out of the box and you just need to enable plugins for your app to get it working. Maybe the UI is not the nicest you would expect (luckily, it is being improved), but having it built in and not interfering with your app is a great plus.
Also, if your build is failing, sometimes it is worth turning on Xcode and Android Studio to build your app there, as their logs may better point you to what is causing the issue. I know, those tools feel like a blackbox and your working machine will surely start loudly complaining, but some familiarity will pay off. Check, for example, this talk on Xcode.
To be honest, debugging errors will take a long time to get used to. For a novice, it is not always apparent where the error is coming from. And, more importantly, it'll take time to figure out if code changes alone can fix the issue, or if you have to reload—or even rebuild—your app. This can make you lose precious time, which is why I recommend documenting the steps you take when resolving common bugs—that's how you will save time later on.
When things are going quite smoothly, something I really enjoy is Fast Refresh, which allows you to see your code changes reflected instantly. Some great news is that this functionality has recently made its way to web development as well.
There's quite a lot to consider when you are building a mobile app in React Native after having worked solely in web development. As such, in this section I would like to touch on a few essential topics that you may find helpful.
All your components are display: flex
and flexDirection: column
as default, so forget grids and blocks and brush up on your flexbox skills. You will often be tempted to use flex: 1
to make your container fill the whole screen or all available space, which is perfectly fine—but remember that these don't have to play nicely if your component has any animation elements and the device has to recalculate the space. Similarly, another default is position: relative
, meaning your absolute elements are positioned relative to their parent.
Forget CSS pseudo-elements and selectors; in React Native, we inline the styles. The recommended approach is to use a StyleSheet object, but I enjoy using Styled Components in a similar way as on the web. If you are a fan of styled systems, Restyle from Shopify is gaining popularity.
You can also choose from several UI kits to get started on your hobby project. Popular ones are, for example, React Native Paper and UI Kitten.
By the way, remember that you don't have semantic HTML elements at your disposal. Most components are View (container) or Text (you cannot use simple text with other components), therefore you may want to think about adding some accessibility props.
You cannot use .svg files as a source for RN's Image component. You will probably end up using pngs, ideally 3x the size to account for iPhones' scale factor—so don't forget to compress it! If you want to use svgs, use React-Native-SVG library and SVGR playground for quick conversion to an RN component.
You can use the built-in Animated API, which performs well especially when using useNativeDriver: true
prop. However, you get the best performance with the React-Native-Reanimated library, which is currently being upgraded to version 2 and expectations are high! Note that this only works with Hermes enabled (see the next section). More sophisticated animations used to, for example, wow users with an eye-catching splash screen, are commonly achieved with Lottie.
In general, there are actually many built-in components within React Native. For example, Activity Indicator (loader) that behaves natively on both Android and iOS, or Flatlist, a component used to display and optimize lists of items, a preferred way compared to mapping over an array as we are used to from the web. The trend is to make the RN library lighter, which is why some nonessential ones were moved to React Native Community repo for maintenance.
One important note for Android: As you add more libraries, you may encounter an error that limits you to a certain number of allowed methods. To deal with this, enable Multidex. Another error may come if you enable Hermes, an optimized Javascript engine for running Android apps and, soon, also iOS. While some libraries—like the above-mentioned Reanimated—require it, others are not yet compatible with it (Realm - see below).
No comment. If you've worked with React Native, you get this. It is a topic one would rather skip. When you work with text inputs, you have to account for the keyboard sliding from the bottom, hence we utilize the Keyboard Avoiding View container that is able to adjust itself and make space for the keyboard. Unfortunately, consistency across iOS and Android is not always there, and you will probably end up adjusting Android's windowSoftInputMode at some point to get the best experience.
Another unpleasant thing you might face is optimizing for the landscape mode. For most apps, it is common practice to just disable it.
To navigate between screens, you will probably end up using the very popular React Navigation library. There is a great, purely native alternative, React Native Navigation (the names get confused easily), from Wix. It is super performant but not that flexible. Therefore, again: If your design asks you for something custom, you have no choice but to go with React Navigation; luckily, it is a great, well-documented option.
The Redux library is quite a common choice thanks to its broad ecosystem. Luckily, there is now a very useful Redux Toolkit that mitigates the amount of boilerplate you have to usually write. RTK Query is a very new Redux solution for data fetching and caching, hopefully making our lives even easier. Though the web seems to slowly be moving away from Redux to React Query, SWR or other solutions, mobile is a different story; Redux is holding on to its popularity, as it integrates well with libraries that persist and rehydrate the global state for users when they relaunch the app.
To persist data on the device, it is common to use AsyncStorage, which is an asynchronous alternative to web's LocalStorage. Another interesting option (though a bit more complex) is to use the Realm database.
Sooner or later, you will encounter a situation where you need to add permissions to your app; for example, to access the camera and photos library during a file upload. Though not always required, it is common to use the React Native Permissions library to offer a consistent experience across platforms.
Further, mobile devices can lose connectivity easily; for that, you can count on the NetInfo library to offer a user experience while offline. Finally, notifications are an essential part of mobile apps and Firebase offers great React Native integrations.
We live in an amazing time. Our React coding skills can easily transfer from web to mobile to build full-fledged iOS and Android apps. Sometimes, this allows us to offer significant cost savings to our clients in the process. Yet one has to understand that mobile and web development do differ and, to offer a great user experience, it is not only about the code we write.
Experienced mobile app developers can easily smell when something is not right, therefore I insist that you put your ego aside and ask them—be it your colleagues or peers on Twitter or Reddit, or anyone with mobile UX know-how—to review your app and provide feedback. Only with this approach can you progress and apply your skills to build great products.
Originally published at aronberezkin.com and strv.com on February 18, 2021.
18