Andrei Calazans

React Native Weekly - W49 2021

☕️ 5 min read

Welcome to the 37th edition of React Native Weekly!

This is week 49 of 2021: November 29th to December 5th.

Fix crash on ReactEditText with AppCompat 1.4.0 [Android]

According to Nicola Corti

This Diff fixes a crash happening as the user uses AppCompat 1.4.0 as a dependency in their App and uses a TextInput component. The crash happens as mFabricViewStateManager is accessed during the constructor of the superclass, and is not yet initialized.


Make fling animator customizable

This change by Xin Chen surfaces the work going on with VR.

Xin attempts to fix the fling animation when you overscroll, he mentions that on VR due to the joystick events it is more evident how the animation is unexpected despite that on mobile it being almost unnoticeable.

For now he only refactored the code to allow for a custom interface to override the fling animation and recommended the in the future the animation gets properly fixed for mobile. And also introduced some fixes to the Android implementation to resolve some unexpected bounce-back effect.

Automating the release cycle

Luna Wei has made multiple changes in the effort of automating the release process, this will enable React Native to ship more versions since today’s process is very manual.

The goal is to be able to publish directly to NPM by running a Circle CI build when there is a push to a release branch.

This is still a work in progress but you can see the progress happening in the below commits:

  • 583471bc48a Fix workflow for automating version bumps
  • 8cc80a843a1 isTaggedVersion checks if the commit has a version tag on it
  • 90f0de99ada Remove warning against PR for release branch
  • 94abcffe2fd Update CircleCI to auto-deploy release branch on push
  • f4314c2b44b Extract logic from bump-oss-version specific to prod releases
  • ea6e34da772 Extract release agnostic logic in bump-oss-version to set-rn-version
  • c611ed1b932 Add getNextVersionFromTags

Fix eslint no-shadow issue with TypeScript enums (#32644)

Commit by Tom Spencer

The current ESLint config includes a rule for no-shadow. When authoring using TypeScript, the typescript-eslint docs mention that the base no-shadow rule should be disabled in favour of typescript-eslint/no-shadow, otherwise false positives can be reported. In my case, I was experiencing the same symptoms as described in this issue.

Screenshot 2021-11-22 at 21 02 31

After changes:

Screenshot 2021-11-22 at 21 03 28

Support queuing accessibility announcements [iOS]

Change by Peter Carpenter

The current implementation of AccessibilityInfo.announceForAccessibility will immediately interrupt any existing in progress speech with the announcement. Sometimes this is desirable behaviour, but often you will want to wait until existing speech is finished before reading the new announcement. This change gives us that option.

The new NativeAccessibilityManager.announceForAccessibilityWithOptions method:

diff --git a/Libraries/Components/AccessibilityInfo/NativeAccessibilityManager.js b/Libraries/Components/AccessibilityInfo/NativeAccessibilityManager.js
index 9ee2403e372..78dc83170ad 100644
--- a/Libraries/Components/AccessibilityInfo/NativeAccessibilityManager.js
+++ b/Libraries/Components/AccessibilityInfo/NativeAccessibilityManager.js
@@ -52,6 +52,10 @@ export interface Spec extends TurboModule {
   |}) => void;
   +setAccessibilityFocus: (reactTag: number) => void;
   +announceForAccessibility: (announcement: string) => void;
+  +announceForAccessibilityWithOptions?: (
+    announcement: string,
+    options: {queue?: boolean},
+  ) => void;

Use same implementation for on iOS and Android

Marc Rousavy refactored the internals of iosPerformanceNowBinder and reactAndroidNativePerformanceNowHook to have the same logic based on Chrono API.

    auto time = std::chrono::system_clock::now().time_since_epoch();
    return std::chrono::duration_cast<std::chrono::milliseconds>(time).count();
const now =
console.log(`${Platform.OS}: ${now}`)

Introduce cleanAll Top Level Gradle task.

Nicola Corti introduced the cleanAll task in Gradle, use this task clean up any left over files.

diff --git a/build.gradle.kts b/build.gradle.kts
index cab3029de00..edc42530435 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -47,3 +47,16 @@ allprojects {
         ext["ANDROID_NDK_PATH"] =  System.getenv("ANDROID_NDK")
+tasks.register("cleanAll", {
+    description = "Remove all the build files and intermediate build outputs"
+    dependsOn(gradle.includedBuild("react-native-gradle-plugin").task(":clean"))
+    delete( { it.buildDir })
+    delete(rootProject.file("./ReactAndroid/.cxx"))
+    delete(rootProject.file("./ReactAndroid/src/main/jni/prebuilt/lib/arm64-v8a/"))
+    delete(rootProject.file("./ReactAndroid/src/main/jni/prebuilt/lib/armeabi-v7a/"))
+    delete(rootProject.file("./ReactAndroid/src/main/jni/prebuilt/lib/x86/"))
+    delete(rootProject.file("./ReactAndroid/src/main/jni/prebuilt/lib/x86_64/"))
+    delete(rootProject.file("./packages/react-native-codegen/lib"))
+    delete(rootProject.file("./packages/rn-tester/android/app/.cxx"))

Move preallocation calls to background [Android]

Andrei Shikov is running an experiment to try to preallocate the views in a background thread on Android.

Preallocation can take 10–20% of time when creating new nodes. (according to systrace measurements). At the moment, we are executing all preallocation calls in JS thread, potentially slowing down the progress there. Moving them to bg thread is a simple micro-optimization that ensures we return the node to JS as soon as possible.

+  if (dispatchPreallocationInBackground_) {
+    auto backgroundExecutor = backgroundExecutor_->get();
+    backgroundExecutor([this, surfaceId, shadowView = std::move(shadowView)] {
+      preallocateShadowView(surfaceId, shadowView);
+    });
+  } else {
+    preallocateShadowView(surfaceId, shadowView);
+  }

Enable Fabric by default inside RN-Tester

Fabric is now enabled by default on Android for the rn-tester. Commit.

Introduce TextInput.setSelection method

This change introduced the imperative alternative to the TextInput selection prop. This way you don’t need to store local state for the start and end values.

The start and end of the text input’s selection. Set start and end to the same value to position the cursor.

this._textInput?.setSelection(start, end)



That’s it for this week. If you want to see more checkout the previous week’s posts here. Subscribe to get notified when new posts are out = )