July 07, 2017

Lessons learned from upgrading React Native whilst angry

I’ve been developing in React Native for the better part of a year and loving it. Before getting into web development I tried doing Android development in Java in 2011 and it was hell. The same year I tried making an iOS game in Objective-C and loathed it. Today, I swear by React Native for mobile app development.

There are, however, some quirks that come with building on a framework who’s split functionality between native code and a JS server that controls the native code (a gross oversimplification of how React Native works, sorry). In my experience, the speed and efficiency gained from working in React Native blows the infrequent annoyances out of the water. And as someone who is primarily a web developer, it gives me a taste of what native mobile devs have to deal with.

Just install the module

I was working on an new app and we wanted a social login. You can do this directly through OAuth and callbacks like you would in a desktop browser, but most big social companies have SDKs for mobile so you can log in through their app natively pretty easily. I think this is a better flow, and for me personally this is a big deal since I use a password generator on my computer but not on my phone. If I can’t log in through the app I just can’t login unless I want to type in a 20+ character random password for each new app.

So we started with Facebook, which has a React Native (RN) wrapper for their SDK. Nice! So I load it in, and huh, some errors. Ok looks like react-native-fbsdk 0.6.1 requires RN 0.44, and we’re on RN 0.43. I don’t feel like upgrading everything just yet so I just roll back to 0.5.1 which supports RN 0.43. Cool, works... kinda. Android gradle builds are messed up and I have to upgrade the gradle projects every 20 minutes but whatever, it works and I hit a good stopping point. Another engineer was building out the api for login, so when he’s done I can just tie it up to the server and test the end-to-end flow without any blockers.

When he’s done I get back on later to test on iOS and get one of the strangest errors I’ve ever seen:

ERR! Something went wrong while linking. Error: Expected “/*”, “//”, or “{“ but “<” found.

Ok thats Not At All Helpful™, but doing some digging it seems that its an XCode project file that got improperly generated. I go through the file… nope seems… fine. There’s a pretty big GitHub issue up where people have been talking about it and I did everything they said and more and I can’t find the same errors they had. Ok so somethings definitely up. However this is the linker for React Native to tie native modules to the JS bridge! If the linker breaks just gotta link it myself manually in XCode, no big deal.


The red rectangle of death

At this point I’m pretty deep in what felt like a fever dream so I don’t remember exactly what got me here, but I finally get the project linked properly and running. I see this weird red box.

“Huh”, I think, “a red rectangle loaded instead of the button that showed up on Android”. It must have been another linking error, and based on what I could see on StackOverflow, yeah it was. So I clean the Xcode project and relink all the parts. Doesn’t compile. Huh. Ok so I rebuild again, relink, clean, everything. Won’t compile. At this point I was still on react-native-fbsdk 0.5.1, and I still had that gradle build issue on Android, so I was like “OK I’m having way to many issues, we have to upgrade RN anyway, might as well now, no big deal”


Upgrade hell

We were on RN 0.43, needed to be on 0.44, and the latest was 0.46. In my frustration and impatience I skipped right to 0.46. That was the worst decision I could have made. Do not upgrade packages while you are angry or annoyed at it. Things were breaking and now android wouldn’t even run. The Node server that serves the JS files was just not working, and I started getting odd errors. I stupidly followed the wrong trail and started installing some packages that seemed to keep fixing stuff, like babel plugins and weird other dependencies that magically appeared, but it all felt wrong and that let me to a wall. So I stashed everything and ditched it. I got back to a stable branch. “Ok, lets upgrade React Native first one version at a time, then load in FBSDK”.

Back to the beginning

As I experienced all at once not long before this, there seemed to be a ton of errors and quirks going from 0.43 to 0.44 to 0.45 t 0.46 at every step. The weirdest one was that react-native run-<platform> just stopped working. So after some quick digging and experimentation I realized I had to first run react-native start --reset-cache every time for a reason that is still not totally clear to me but it seems to be related to a change in file structure defaults between 0.43 and 0.44 when create-react-native-app was added to the cli to make it easier for new RN devs to make a project… I think.

Finally I installed react-native-fbsdk again, finally figured out how to fix the gradle errors on android, still had to manually link to XCode, but then at long last I ran on iOS.


Ok what step am I missing… I did everything, right? I had to have. I checked the docs for the FBSDK again and again, and it seemed that I had everything verified and linked! The only issue I had now was the redtangle. Everything was building so what was the problem?

For some reason, the linked sub-frameworks that were linked through the FBSDK were not properly linked. They showed up in the list but in the sidebar were red. “Red means bad.” I learned that from the rectangle. So I dropped in the sub-frameworks both directly to my project’s dependencies and also to FBSDK itself. BAM! Briefcases! “Briefcase means good” I assume, as anyone would. Apparently the ones it was linking to just either weren’t there or the framework PATH I specified wasn’t cooperating so it couldn’t find the ones I just dropped in without my actually linking them explicitly.

Moment of truth… react-native run-ios



The rest of the story is me just actually implementing the rest of the authentication features, I won’t bore you with that. But I will leave you with a moral to this story:

Do not upgrade libraries angry.

You will skip steps, and you will overlook errors. Take it slow and verify things work on each step. The distractions from the the upgrades breaking prevented me from properly finding the source of the linking errors.

And with that, happy developing!