React Native is made for shipping, not maintainability
After two years of React Native development, I have come to realize this.
I am a graduate in computer science from the University of Padua, I started developing for iOS in 2010 and I was a iOS developer until early 2019.
How I started with React Native
In 2019 I was lucky enough to land a job in Foodracers, an Italian food delivery startup based on the city where I live, Treviso. Given the experience I gained in the previous years in the mobile world, they trusted me with the development of their mobile apps. There was a catch, though: the apps had to be written using React Native for the two main reasons everyone chooses this platform: the other developers were familiar with web technologies, and the write once, run everywhere approach was desirable.
Being curious about stuff I don’t know, I accepted the challenge, rolled up my sleeves and began to study. A big shout-out to Maximilian Schwarzmüller and his React and React Native courses on Udemy. I was on track in few days and ready to experiment with real-world scenarios.
The first app I got to develop was the one for our riders, or Racers as we call them. It was a fairly complex app, but this is not the point 😀
When I started, in June 2019, the latest React Native release was 0.58.4. After a couple of months of hard work, it was ready. And surprise surprise: the latest release at the time had become 0.60.5. “No biggie” I thought, I will update it and it will just work. It was not the case.
My experience with updates
I see two main issue with maintaining a React Native project long term: one is keeping up with the React Native dependency itself, that allows to keep the compatibility of the app with new updates of the operating systems; the second one is keeping the dependencies updated, both for security and for compatibility.
Following, I will describe my experience in maintaining three apps up to date. It surely is limited by the little time I spent on these issues, but I think they are often overlooked when choosing the technology to use to develop a brand new app.
As stated before, when I started my adventure with React Native the latest release was 0.58.4. As I am writing, the latest public release is 0.63.4, and v. 0.64.0 is currently in pre-release, with rc2 available. In less than two years, 32 stable versions have been released. With these numbers, it is very difficult to keep up with every version. What I tend to do is to avoid .0 releases, since they are often buggy and patch versions are released soon afterwards. Still, patch updates are almost always painless.
The pain starts for minor versions updates. Facebook provides an upgrade helper, but more often than not I cannot make it work properly. As far as I read online, with the newest releases it is supposed to work better and better. After a lot of time spent on git diffs and trying to make it all work smoothly, my personal experience is that the safest way to make it work is to begin with a brand new project, install the dependencies (one at the time) and import the source code. It’s a fairly long process, but there are no doubts it is effective. The only issues that usually arise are due to the compatibility of the dependencies: sometimes different versions are required and thus changes to the source code must be done.
One of the advantages to use React Native over other hybrid platforms, such as Flutter or Ionic, is the huge community that supports it with open source libraries. But with great power comes great responsibility, an in our case that means maintaining those libraries. In the vast majority of cases this happens, but we still must keep them updated, since bugs get fixed, new functionalities are added, and above all new requirements from the operating systems are met. Even though backwards compatibility is often guaranteed, sometimes it is overlooked (React Navigation and Firebase, I’m looking at you). To avoid this kind of situations, I wrap the usage of the library as much as possible in my own components or objects. Thus, I am sure that if some changes are required on the code base, I just need to make them in one place and everything works fine.
Sometimes, though, it is just not possible, such as in the React Navigation update from version 4 to 5. I won’t go into specifics, but the changes in the managements of navigators and navigation between screens were massive. Unfortunately, it was necessary due to a layout issue happening in iPhone 12. So in those cases, all you need to do is suck it up and refactor.
One of the biggest problem with libraries is depending on one that gets deprecated. This is a big issue because once the compatibility with newest systems or devices is broken, there’s just no way out. That’s why I tend to have as little dependencies as possible, and trust only the most used and maintained ones. For smallest tasks I try to write my own stuff as much as possible; this decreases the development speed but increases maintainability and gives me a chance to practice with something new once in a while .
React Native is a great tool to ship apps fast, it has a great community and it is based on a straightforward technology. But it’s not all fun and games. While starting on a new project, keep in mind that maintaining a React Native code base has some drawbacks on the long term, and eventually you must face them. It can become frustrating at times, be ready to pass some time refactoring your code base or rewriting stuff from scratch.