Updating Your React Native App

Congratulations, you’ve written your first React Native app and users are downloading it from the store.

Now what?

React Native is a rapidly changing framework. New versions are released monthly and breaking changes are common. You should do your best to regularly update to the latest version of React Native so that your app can benefit from the new features and improvements to speed. Going more than a few months without upgrading can result in a painful upgrade process.

In my work at Build.com, I’ve upgraded our React Native app from version 36 to version 45 over a couple big projects. Each upgrade is different based on the libraries you are using, the current version of React Native in your app and the target version that you’re upgrading to.

But given all that, I’ve come up with a process that helps me:

Getting Started

  1. Begin by reviewing the React Native release notes for all of the releases between your version and the target version. Specifically, you’re looking for any breaking changes or deprecated features that will affect your project. Make note of them and any new features that you’re interested in using.
  2. Review the libraries in your package.json, ios/Podfile (if you're using Cocoapods), and manually installed in Xcode or Android Studio. Check the website for each library to see if it is compatible with your target version. If a library hasn’t been updated to support a newer version, you may need to clone it and make the updates yourself. Try to submit a pull request back to the main library, if possible. This problem was very common when React Native v40 was released with a number of breaking changes. Often libraries will be dependent on a lower version of React or React Native but they will work with a newer version. Github Issues will often help you discover this. If this is the case, you can ignore the warning from npm, or you can fork the library and update the dependencies
  3. If you haven’t already, install react-native-git-upgrade or see the section on rn-diff below (recommended)
  4. Update your code and start a clean branch

Begin the Upgrade

Update: I finally tried out rn-diff and I now recommend it over react-native-git-upgrade. See below for more details and skip this entire section

  1. Run the react-native-git-upgrade tool. Generally, I update one version at a time and try to work it to the point where it is at least compiling on one of the platforms. Update to the latest patch of the version you’re looking at. For example, when upgrading to v44, I upgraded the app to v44.3 because that had the highest patch number
  2. After the upgrade tool runs, you’ll likely get a series of files that failed to automatically merge. You’ll need to solve the conflicts in these files
  3. If ios/MyApp.xcodeproj/project.pbxproj (or other Xcode config files) fails to merge, it’s usually best to look at the diff (using git diff or something like DiffMerge) to determine if any of the changes are necessary. In our app, the changes to that file usually involve deleting our custom Xcode schemes. If there are necessary changes, you can note them, roll back the merge using git checkout -- ios/MyApp.xcodeproj/project.pbxproj and then manually apply them in Xcode

Upgrading Your Other Libraries

  1. Upgrade your libraries in package.json and the Podfile per the research you did above. If you’re upgrading several versions it can sometimes be difficult to tell which versions of your libraries support the target version of React Native. The npm warnings can help with this or the library’s release notes
  2. Run the Delete Script at the bottom of this article to get a fresh set of packages. After npm install completes, look for any unmet dependencies or warnings and decide if you need to/can update those libraries
  3. Attempt to compile/build the app with Xcode, Android Studio, or the CLI, react-native run-[ios|android]
  4. If the build fails, check the errors. If you’re getting compiler errors, you’ll need to use your best Google-fu to find a solution to the error. A CFBundleIdentifier Does Not Exist error usually indicates that the true error occurred earlier on in the process and you need to look higher in the logs for the root cause
  5. Repeat the Delete Script/compile steps to see if you’ve cleared the errors
  6. Occasionally during this process, Xcode will lose its references to the libraries you’ve installed. The simple but laborious solution is to delete (remove references) to all of the broken libraries in Xcode and then reinstall them per the directions. This may be associated with trying to manually edit the react-native-git-upgrade merge to project.pbxproj
  7. For some versions of React Native (versions with large breaking changes), the recommendation has been to delete your project, create a new one and copy your code over. No, I’m not joking; why are you laughing?

Finishing the Upgrade

  1. After you can successfully compile, run the app in the simulator. This will help turn up any changes to the React Native API. Make any necessary updates to your JavaScript code to get it to (hopefully) run in the simulator
  2. Once it compiles and runs on at least one platform, I usually start working on the next version. Sometimes it is very difficult to get the app to compile due to library incompatibilities. In that case, just move on to the next version
  3. Don’t forget to commit your code once you get a new version working!
  4. Repeat the process until you’re at the last version. Then you have to test to make sure the app is working correctly

Delete Script

We use this Delete Script pretty frequently at work. It fully clears out all of the caches, and re-downloads and installs the libraries. The pod commands are only necessary if you’re using Cocoapods.

$ watchman watch-del-all
$ rm -rf node_modules
$ rm -rf $TMPDIR/react-*
$ rm -rf $TMPDIR/npm-*
$ rm -rf ios/Pods
$ pod cache clean --all
$ pod repo update && pod install
$ npm install
$ ./android/gradlew clean -p ./android/
$ rm -rf ios/build
$ npm start -- --reset-cache

The $ signifies a new line on the command prompt or Terminal window.

Using RN-DIFF

Update to the original post.

On my most recent upgrade of our app (from 45 to 48), I took the opportunity to use rn-diff as recommended by @andreneves and @pvinis and it was fantastic. Way easier to use than react-native-git-upgrade. I never realized that the differences were so small from one version to the next.

rn-diff is a repo that tells you the differences from one version of an app created using the React Native CLI to the next. When you visit the repo, you’re presented with a huge table that lists every major, minor and patch version for React Native and gives you the ability to compare the changes from one version to the next.

And for the most part, these changes are exceedingly minor! In many cases, the only change to the default app was a change to the version number in package.json.

My new process is to simply go through each comparison view in the table (version by version) and copy the changes over to my code base. I’m sure I could use git and the patch files to copy the changes over but I like to see them and like I said, often the only change is to increment the version numbers in package.json.

The minor version updates appear to be a little more complicated than the patch but, for example, the upgrade from 0.48.4 to 0.49.0 involved a changing a couple dozen lines across 5 files so it’s not that difficult.

I did the last upgrade solely with rn-diff and I would recommended it for everyone unless you have some weird scenario. And I would still guess that rn-diff is easier for most of the weird scenarios.