Welcome to the sixth edition of React Native Weekly = )
Reach out to me via Twitter if you have any feedback, and don’t forget to subscribe!
Defensive Programming - NativeEventEmitter Checks Add & Remove Listener
Now, the NativeEventEmitter
checks if the native module it received when instantiated has add and remove event listener methods.
+ const hasAddListener =
+ !!nativeModule && typeof nativeModule.addListener === 'function';
+ const hasRemoveListeners =
+ !!nativeModule && typeof nativeModule.removeListeners === 'function';
+
+ if (nativeModule && hasAddListener && hasRemoveListeners) {
Bump Gradle Wrapper To 6.8.3
This is preparation for Gradle 7.0 version, which supports Apple Silicon natively.
RuntimeScheduler
The Runtime Scheduler continues to be worked on, the efforts here are all related to Fabric - the asynchronous scheduling system that has priority queues. Most of the work seems to happen in coordination with the React Core team.
Some updates were:
Pass hardcoded false argument to scheduled callbacks
Scheduled callback function expects a boolean param to indicate if a callback timed out. React Core team will remove it, thus they are hardcoding it for now.
void Task::operator()(jsi::Runtime &runtime) const {
+ // Cancelled task doesn't have a callback.
if (callback_) {
- // Cancelled task doesn't have a callback.
- callback_.value().call(runtime, {});
+ // Callback in JavaScript is expecting a single bool parameter.
+ // React team plans to remove it and it is safe to pass in
+ // hardcoded false value.
+ callback_.value().call(runtime, {false});
}
}
Implement task continuation
Commit comment:
Scheduler’s callback have option to add more work inside callback. This work stays on top of the priority queue and gives React ability to flush all work synchronously if need.
This diff adds use of shouldYield_
to the workLoop. For now, it always evaluates to false. In the future when we allow access to the scheduler to native, it will allow yielding.
Fix for ‘An Unexpected error occurred’ caused by DatePickerDialog.
This was a fix introduced because of a error they caught in the Messenger Kids app. The main change is just handling the UI update within the UI thread, on Android you can only make UI changes within the UI thread.
--- a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogModule.java
+++ b/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogModule.java
...
+ activity.runOnUiThread(
+ new Runnable() {
+ @Override
+ public void run() {
[iOS] Fix InputAccessoryView disappearing when inputAccessoryViewID exists
Commit comment:
InputAccessoryView disappears on Fabric (not Paper) when the text prop changes.
Bridgeless support for RCTSourceCode
I’m not 100% sure how this can be or will be used, but it is simply allowing you to set a URL for your JS bundle instead of a bridge. Let’s see if future updates tells us more.
Fix crash - check if backgroundColor is null before trying to fetch it in ViewProps isLayoutOnly
Commit comment:
Summary:
Noticed while working in MobileHome with android device, when interacting with the Tasks change progress/priority components (MobileHomeTasksDetailsSelectorToken), which provides borderRadius
style and backgroundColor: ifSelected ? value : null
, and when backgroundColor
is null
, the line changed in this diff crashes (throwing the NoSuchKeyException
at ReadableNativeMap:110
[because of isNull check on ReadableNativeMap:107
])
iOS 14 Support new DatePicker styles
This was mostly about adding if checks for iOS version like:
+ if (@available(iOS 13.4, *)) {
And setting the view.preferredDatePickerStyle
with the right value.
Some height updates to the overall look also happened.
Introduce drainMicrotasks to JSI
JavaScript VMs (JSVMs) implement internal Microtask (a.k.a. Job in ECMA262) queue to handle job queue (like promises).
This commit implements a new JSI API drainMicrotasks
to define how hosts may integrate with the JSVMs’ internal microtask queue.
Xuan Huang (jsx@fb.com>) documented his changes quite well with extensive comments around his decisions. If you are curious check out the commit and the jsi.h file which has more comments about the drainMicrotasks
.
Here is an short snippet of something Xuan explained:
Notes on the existing APIs from JSVMs
The presence of such queue and APIs to operate on them are ubiquitous:
- Hermes:
Runtime::drainJobs
- V8:
MicrotaskQueue::PerformCheckpoint
- JSC:
VM::drainMicrotasks
- QuickJS:
JS_ExecutePendingJob
The only exception is ChakraCore, which requires hosts to provide
the queue and set up the JsSetPromiseContinuationCallback
,
but a JSI implementation can provide that queue trivially.
Perform Engine Microtasks in JSIExecutor
Xuan Huang (jsx@fb.com>) did further work on the Engine Microtasks:
This diff introduce a helper performMicrotaskCheckpoint
to
repetitively invoke jsi::Runtime::drainMicrotasks
to exhaust
the microtasks queue provided by JS VMs
Refactor: Move RuntimeExecutor into Instance.cpp
While the change is trivial, the commit message explains something interesting about the pieces of React Native’s architecture such as NativeToJsBridge
, RuntimeExecutor
, and Instance
.
RuntimeExecutor is currently declared inside NativeToJsBridge. It doesn’t need to be: Instance.cpp can use NativeToJsBridge::runOnExecutorQueue to schedule work on the JS Thread. So, this diff moves RuntimeExecutor out of NativeToJsBridge into Instance.cpp. Now, both the JS CallInvoker and the RuntimeExecutor are declared in the same file.
Add flushing to RuntimeExecutor
Motivation
With the bridge, every call into JS flushes the queue of NativeModule calls. Fabric bypasses this mechanism, because it uses a RuntimeExecutor that schedules work directly on the JavaScript thread. This diff makes Fabric’s RuntimeExecutor also flush the queue of NativeModule calls.
This likely won’t fix anything in Fabric, because we don’t execute any async NativeModule calls on Fabric. However, this is necessary for the drainMicrotask work we’re doing
--- a/ReactCommon/cxxreact/Instance.cpp
+++ b/ReactCommon/cxxreact/Instance.cpp
+ if (shouldFlush) {
+ executor->flush();
+ }
Removed getNode()
from Animated Component Refs
This was predicted since there were warnings already.
diff --git a/Libraries/Animated/createAnimatedComponent.js b/Libraries/Animated/createAnimatedComponent.js
index 45859bb111..c86e63cd88 100644
--- a/Libraries/Animated/createAnimatedComponent.js
+++ b/Libraries/Animated/createAnimatedComponent.js
@@ -198,19 +198,6 @@ function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
setLocalRef: ref => {
this._prevComponent = this._component;
this._component = ref;
-
- // TODO: Delete this in a future release.
- if (ref != null && ref.getNode == null) {
- ref.getNode = () => {
- console.warn(
- '%s: Calling `getNode()` on the ref of an Animated component ' +
- 'is no longer necessary. You can now directly use the ref ' +
- 'instead. This method will be removed in a future release.',
- ref.constructor.name ?? '<<anonymous>>',
- );
- return ref;
- };
- }
},
});
How Hermes shranked their heap by 30%
Tzvetan Mikov, Hermes’ tech lead, shared some insight into how they reduced the engine’s heap usage by 30%. He explained they introduced a 32-bit value encoding for values stored in the heap since now all values require 64-bit encoding.
Callstack’s Post On Hermes’ Performance On iOS
Beatgig - A Web, iOS, and Android codebase using React Native
Fernando Rojo is always showing off cool animations he accomplishes with his library Moti, this time he shared cross-platform app he is building which looks amazing.
Removing Console Logs In Production
Evan shared with us that you can set Metro’s drop_console
value to true and have all console logs removed.
That Is It!
That’s it for this week. If you want to see more checkout last week’s post here. Subscribe to get notified when new posts are out = )