React-native: Root component sometimes mounted twice on Android in development

Created on 22 May 2018  路  12Comments  路  Source: facebook/react-native

Android users reported an issue on react-navigation that is caused by a component being mounted twice where we only expect it to be mounted once (https://github.com/react-navigation/react-navigation/issues/4196). I dug into the root (no pun intended) cause and found that the problem was caused by the app root component mounting twice.

Environment

Environment:
OS: macOS High Sierra 10.13.4
Node: 9.2.0
Yarn: 1.5.1
npm: 5.7.0
Watchman: 4.7.0
Xcode: Xcode 9.3 Build version 9E145
Android Studio: 3.0 AI-171.4408382

Packages: (wanted => installed)
react: 16.3.1 => 16.3.1
react-native: 0.55.4 => 0.55.4

Steps to Reproduce

  1. Clone https://github.com/brentvatne/android-double-mount-repro OR just add logs to componentDidMount and componentWillUnmount on the root component of a new react-native init app.
  2. Open the project on Android: react-native run-android
  3. Press the home button to go to the home screen, then tap on the app icon to open the app again
  4. Notice that in logs you will see the logs from componentDidMount
  5. Reload the app (r, r) and notice that you will see componentDidMount log twice, but componentWillUnmount does not ever get logged.

Expected Behavior

Root component should only ever be mounted once on app start

Actual Behavior

Root component is mounted twice on app start

Bug Partner Android Expo

Most helpful comment

I couldn't get your cloned app to build using those instructions, but I've run into a similar error in the past.

In your app/src/main/AndroidManifest.xml, try changing:

 <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"

to

 <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:launchMode="singleTask"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"

All 12 comments

+1

Uhm so it seems to be related to Android "interfering" with the React lifecycle or at least not properly unmounting when going in the background? 馃

Could it be related to the version of Android the app is running on / being targetted against (ex. v23 VS v27)?

Weirdly reminds me of this old issue https://github.com/react-navigation/react-navigation/issues/2599 which was fixed by this https://github.com/react-navigation/react-navigation/pull/3224 (just linking for reference)

OK, i face this problem right now, and i found that because our android developer change some native code, seems android developer code new another Activity!!!!
hope that helpful

I couldn't get your cloned app to build using those instructions, but I've run into a similar error in the past.

In your app/src/main/AndroidManifest.xml, try changing:

 <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"

to

 <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:launchMode="singleTask"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"

I can reproduce this easily. Clicking the home button of the android phone, does not trigger "unmount", however subsequently clicking the app-icon from the home screen triggers my root component's "constructor" and "mount", leaving the old instance of these objects still running. Have tried @Meandmybadself 's suggestion which doesn't change this behavior.

We get this constantly in our app. We're using react-native 0.57.4, react 16.6.0 and react-navigation 2.18.2 in production. We have android:launchMode="singleTask" in our android manifest

Experiencing the exact same thing, ends up double instantiation of our router and horrible performance

We have noticed that we especially get it when we open the app through a push notification grouped by the OS (Android >8)

As in there are multiple push notifications and the OS automatically groups them by app. When we click these something weird happens with the instantiation.

Not sure if it is relevant for this issue, but I hope it helps someone debug: When we removed our splash screen the issue disappeared!

We had

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class SplashActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = new Intent(this, MainActivity.class);
        startActivity(intent);
        finish();
    }
}

and this caused the main activity to reinstantiate when the app came to foreground through OS grouped push notifications. We set up react-native-splash-screen instead and the problem went away

Be sure to add android:launchMode="singleTask" to activity not to application as I did first. Then I added it to activity and it works!

It still happens even with android:launchMode="singleTask" 馃槙

still occurring even though I have all the changes mentioned by @Meandmybadself

{
   ...
   "react-native": "0.59.10",
   "react-navigation": "3.9.1",
   ...
}
Was this page helpful?
0 / 5 - 0 ratings