react-native: Android back button causes re-mounting of the root component

Description

Upon putting the Android app into the background by using the hardware back button and then re-opening the app, the entire app gets re-initialised and all the root components code gets executed again (constructor, componentDidMount). This causes things like event listeners to stack up.

What I expect to happen when pressing the back button is for the app to just go into the background, just like pressing the home button on iOS. When you open the app back up, nothing should re-initialise.

Reproduction Steps and Sample Code

  • Initialise a new RN project at version 0.44.0 called “TestApp”
  • Add the following code to the index.android.js
/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';

let count = 0;

export default class TestApp extends Component {
  componentDidMount() {
    count++;
    console.log('mounted', count);
  }

  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to React Native!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit index.android.js
        </Text>
        <Text style={styles.instructions}>
          Double tap R on your keyboard to reload,{'\n'}
          Shake or press menu button for dev menu
        </Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

AppRegistry.registerComponent('TestApp', () => TestApp);
  • Run the app within the Android Simulator (I’m using an Nexus 4, Android 6.0)
  • Turn the debug console on within the simulator so you can watch the console logs in Chrome
  • You should then see “mounted 1” in the console
  • Now close the app by pressing the hardware back button
  • Now click the app icon on the home screen to open the app back up
  • The console will now log “mounted 2”
  • You can then repeat this process indefinitely see the mounted count increase

Solution

Stop the app re-mounting when the Android app is closed from the hardware back button or explain if this is expect behaviour and why it’s different from pressing the hardware home button.

Additional Information

  • React Native version: 0.44.0
  • Platform: Android
  • Development Operating System: MacOS
  • Dev tools: Android Studio 2.2.3

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 11
  • Comments: 19 (6 by maintainers)

Most upvoted comments

I needed to combine the answers of @vjeranc and @ms88privat in order to get it working.

// MainActivity.java
@Override
public void invokeDefaultOnBackPressed() {
    moveTaskToBack(true);
}
<!-- AndroidManifest.xml -->
<activity
    ...
    android:launchMode="singleTop">

Doesn’t this mean your main activity is destroyed by the back button and new one is initialized?

componentWillUnmount should execute when exiting the app.

If you do not want to destroy MainActivity put the implementation below for backpress.

@Override
public void invokeDefaultOnBackPressed() {
    moveTaskToBack(true);
}

I noticed very similar behavior to this when using the home button. Oddly enough it was only on the initial launch of the app.

react-native init Testing
cd Testing
react-native run-android

Once the app launches minimize with the home button and launch it again. You can now hit the back button to close the second instance that was created and return to the first.

If you hit the back button enough to force the app the close this issue doesn’t reoccur on additional launches.

android:launchMode="singleTop" seems to clear it up.

Have the same issue (for me react-redux connect will be stacking up and firing multiple times , for each pressing home button and relaunching app ) , also it looks like each time when app goes from background to active state componentDidMount is called, how ever when we press home button componentWillUnmount is not called.

We encountered this issue on android on a project at work. The first time you installed the app, if you pressed home and then re-opened the app then the root component would re-initialize. The issue manifested with a video player, where you would hear two videos playing over the top of each other. The problem would compound each time you pressed home and re-opened the app - it was as if react-native was re-instantiating multiple copies of the app on top of each other! If you killed the app completely, then the problem would not re-manifest. It only happened the first time you installed, and if you had not yet closed the app. @birgernass that fix seems to resolve the issue though!