shirakaba / react-nativescript

React renderer for NativeScript
https://react-nativescript.netlify.com
MIT License
280 stars 14 forks source link

Guard against potential NSCore bug: firing second ```create()``` event on app foregrounding #70

Closed ujwal-setlur closed 3 years ago

ujwal-setlur commented 3 years ago

As discussed extensively on Slack, it looks like NS Core is firing a create() event when app is brought back into foreground on Android.

Here is the stack trace:

Installing on device 190d41d4ee6ba084...
Successfully installed on device with identifier '190d41d4ee6ba084'.
Restarting application on device 190d41d4ee6ba084...
Successfully synced application org.nativescript.NSReact on device 190d41d4ee6ba084.
JS: HMR: Hot Module Replacement Enabled. Waiting for signal.
JS: [ReactNativeScript.ts] start(). hasLaunched(): false existing rootView was: undefined []
JS: [appendChildToContainer()] deferring to appendChild(): NSVRoot:null > NSVElement:GridLayout(1) []
JS: Container updated! [] <-- INITIAL APP LAUNCH

APP SENT TO BACKGROUND

JS: Container updated! [] <-- APP BROUGHT BACK INTO FOREGROUND
System.err: An uncaught Exception occurred on "main" thread.
System.err: Unable to start activity ComponentInfo{org.nativescript.NSReact/com.tns.NativeScriptActivity}: com.tns.NativeScriptException: Calling js method onCreate failed
System.err: TypeError: Cannot read property 'nativeView' of undefined
System.err: 
System.err: StackTrace:
System.err: java.lang.RuntimeException: Unable to start activity ComponentInfo{org.nativescript.NSReact/com.tns.NativeScriptActivity}: com.tns.NativeScriptException: Calling js method onCreate failed
System.err: TypeError: Cannot read property 'nativeView' of undefined
System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2951)
System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3086)
System.err:     at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
System.err:     at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
System.err:     at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
System.err:     at android.os.Handler.dispatchMessage(Handler.java:106)
System.err:     at android.os.Looper.loop(Looper.java:193)
System.err:     at android.app.ActivityThread.main(ActivityThread.java:6718)
System.err:     at java.lang.reflect.Method.invoke(Native Method)
System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:917)
System.err: Caused by: com.tns.NativeScriptException: Calling js method onCreate failed
System.err: TypeError: Cannot read property 'nativeView' of undefined
System.err:     at com.tns.Runtime.callJSMethodNative(Native Method)
System.err:     at com.tns.Runtime.dispatchCallJSMethodNative(Runtime.java:1302)
System.err:     at com.tns.Runtime.callJSMethodImpl(Runtime.java:1188)
System.err:     at com.tns.Runtime.callJSMethod(Runtime.java:1175)
System.err:     at com.tns.Runtime.callJSMethod(Runtime.java:1153)
System.err:     at com.tns.Runtime.callJSMethod(Runtime.java:1149)
System.err:     at com.tns.NativeScriptActivity.onCreate(NativeScriptActivity.java:29)
System.err:     at android.app.Activity.performCreate(Activity.java:7144)
System.err:     at android.app.Activity.performCreate(Activity.java:7135)
System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2931)
System.err:     ... 11 more

Here is a guard for the create() callback:

    let _hasCreated = null;    
    run({
        create: () => {
            if(_hasCreated) {
                return _hasCreated;
            }
            _hasCreated = true;
            const root = new NSVRoot();
            render(app, root, () => console.log(`Container updated!`), "__APP_ROOT__");
            _hasCreated = root.baseRef.nativeView;
            return _hasCreated;
        },
    });
shirakaba commented 3 years ago

Fixed in NativeScript Core 7.0.12: https://github.com/NativeScript/NativeScript/issues/8828#issue-comment-box