The normal upgrade process applies, however, to upgrade smoothly it is useful to understand what’s new and why you need to make certain changes to your project.
Make sure to take a look at the full changelog for full details on what is included in this release.
Struggling to upgrade to the latest version of React Native?
As always, it is good to run through a few checks before you perform an upgrade. Firstly, and especially if you are going to install a .0 version, check the React Native issue tracker to see if there are any major issues with the new release which might affect you. You should also go through the libraries that you use and see if anyone is reporting any compatibility issues with the new version.
By doing this before starting, you can save yourself some time running into known issues and instead wait until patches are released which make the process smoother.
Assuming that there doesn’t seem to be any blockers, you are ready to start upgrading.
As with all React Native upgrades, it is recommended that you take a look at the diff for the newly created projects and apply these changes to your own project.
You can do this using the rn-diff-purge tool and the diff I will be talking you through is the one between 0.56.1 and 0.57.8. You can just follow this diff and make the changes yourself, however, I want to explain to you what each of these changes means to give you a much better understanding of why you need to make the changes.
The first step is to upgrade the dependencies in your package.json
and install them. Remember that each React Native version is tied to a specific version of React, so make sure you upgrade that as well. You should also make sure that, if you use it, react-test-renderer
matches the React version. We also need to remove the old babel-preset-react-native
package and replace it with the new metro-react-native-babel-preset
one. More details on that later.
"dependencies": {
- "react": "16.4.1",
- "react-native": "0.56.1"
+ "react": "16.6.3",
+ "react-native": "0.57.8"
},
"devDependencies": {
"babel-jest": "24.7.1",
- "babel-preset-react-native": "^5",
"jest": "24.7.1",
+ "metro-react-native-babel-preset": "0.53.1",
- "react-test-renderer": "16.4.1"
+ "react-test-renderer": "16.6.3"
},
First an easy one. The version of Flow which React Native uses has been updated in 0.57. The means that you need to make sure that the flow-bin
dependency you have is set to ^0.78.0
and you have the same value in the [version]
your .flowconfig
file.
[version]
- ^0.75.0
+ ^0.78.0
There are also a few changes to the options that are enabled:
[options]
emoji=true
+ esproposal.optional_chaining=enable
+ esproposal.nullish_coalescing=enable
If you are using Flow for type checking in your project, this might lead to additional errors in your own code. I recommend that you take a look at the changelog for the versions between 0.75 and 0.78 to see what might be causing them.
If you are using Typescript for type checking you code then you can actually remove the .flowconfig
file and the flow-bin
dependency and ignore this bit of the diff.
If you are not using a type checker at all then I highly recommend you look into using one. Either option will work, however, my personal preference is to use Typescript.
React Native 0.57 uses a new package from it’s Babel preset. React Native is packaged using Metro which internally uses Babel to compile your code. The metro-react-native-babel-preset
package defines the default configuration that is used by React Native projects. Previously, it was called babel-preset-react-native
.
You already added the correct package with the changes to package.json
. The next step is to change your .babelrc
file to use the new package:
{
- "presets": ["react-native"]
+ "presets": ["module:metro-react-native-babel-preset"]
}
If you have any customisations to your Babel config you should be able to keep them all as they were before.
React Native 0.57 has various changes to the Gradle build tools and Android Gradle plugins.
Firstly, you need to change how the Google Maven repository is defined. Maven repositories are listed in your Gradle build scripts and Gradle will use them to look for the dependencies you ask for. Make the following changes and make sure the new google()
lines are above any jcenter()
lines:
buildscript {
repositories {
- maven {
- url 'https://maven.google.com/'
- name 'Google'
- }
+ google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
mavenLocal()
- maven {
- url 'https://maven.google.com/'
- name 'Google'
- }
+ google()
jcenter()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
}
}
This version of React Native upgrades the version of Gradle and the Android Gradle Plugin that it uses. You need to make the version changes in the android/build.gralde
file:
buildscript {
+ // Move the ext block to here if you prefer
repositories {
google()
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.3.3'
+ classpath 'com.android.tools.build:gradle:3.1.4'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
mavenLocal()
google()
jcenter()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
}
}
ext {
- buildToolsVersion = "26.0.3"
+ buildToolsVersion = "27.0.3"
minSdkVersion = 16
- compileSdkVersion = 26
+ compileSdkVersion = 27
targetSdkVersion = 26
- supportLibVersion = "26.1.0"
+ supportLibVersion = "27.1.1"
}
+ task wrapper(type: Wrapper) {
+ gradleVersion = '4.4'
+ distributionUrl = distributionUrl.replace("bin", "all")
+ }
There are some changes to the Android SDK versions we are using. With Android there are three SDK versions which we need to specify:
minSdkVersion
: This specifies the minimum Android version which our app supports. Even through React Native is using APIs which were added between 16 and 28 it has fallbacks which means that it can support Android devices all the way down to platform level 16 (known to users as 4.1). Leave this set to 16
unless you use a library which requires a higher Android version.compileSdkVersion
: This specifies the Android SDK which will be used to compile our app. We want to use APIs which were added in Android SDK 28, so we need to set this to at least 27
.targetSdkVersion
: This set the SDK which we are “targeting”. When a new Android SDK is released which includes new or changed behaviour, the Android system will use this values to selectively turn off these changes and put the app into a “compatibility mode”. The allows apps which expected the behaviour of a certain version to still work on new versions of the operating system. We want to leave this as 26
now.Also note that the default project template has moved the ext
block to inside the buildscript
section. I recommend you move yours as well, but it’s not 100% necessary.
Note as well the addition of a new wrapper
task which was added to the bottom of the file.
You also need to update the version of Gradle that is referenced in the android/gradle/wrapper/gradle-wrapper.properties
file:
- distributionUrl=https\://services.gradle.org/distributions/gradle-3.5.1-all.zip
+ distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
The Gradle wrapper scripts have also been updated. These are the android/gradlew
, android/gradlew.bat
, and android/gradle/wrapper/gradle-wrapper.jar
files. These scripts are used as a wrapper around the Gradle tool. It will download the correct version if it’s not already present which allows different projects on the same system to use different versions of Gradle without issue.
You can use the diff to update the files, however, it’s easier to just grab a copy and replace the files directly:
The new version of the Android Gradle Plugin requires new syntax for declaring dependecies in your android/app/build.gradle
file. In most cases you just need to change any reference to compile
in the dependencies
block to implementation
.
dependencies {
- compile fileTree(dir: "libs", include: ["*.jar"])
+ implementation fileTree(dir: "libs", include: ["*.jar"])
- compile "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
+ implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
- compile "com.facebook.react:react-native:+" // From node_modules
+ implementation "com.facebook.react:react-native:+" // From node_modules
}
You will also need to update this for any other dependencies that you have. Libraries which also have their own dependencies will also need to update their syntax, however, the old compile
syntax will still work for now and will just produce a warning.
This change is needed due to a new system of dependency configuration. These configurations allow you to choose when the library is available and if it is included in your build output. implementation
is the main one you will use in your app, the rest are mainly useful for libraries or fully native apps.
Lastly, there is a minor change to the ios/AppDelegate.m
file where the JS code location is determined. Previously, it would only try to load from the Metro bundler and you would need to change the code for release builds. The new change uses a pre-processor macro to automatically change the code for non-debug builds.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURL *jsCodeLocation;
- jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
+ #ifdef DEBUG
+ jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
+ #else
+ jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
+ #endif
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"RnDiffApp"
initialProperties:nil
launchOptions:launchOptions];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
Those are all of the changes that you are required to make for all projects, however, there are a couple of other breaking changes which might affect some apps. You should read through the changelog to see if anything applies to your project. You should also go through the libraries you use to see if any upgrade is required.
Struggling to upgrade to the latest version of React Native?