54

Is it possible to know if a RN app has gone to background? Any callback or trigger?

If I listen to componentDidUnmount or componentWillUnmount of the screen I'm on, it will only be fired if I go back/forth to another screen

Ronan Boiteau
  • 9,608
  • 6
  • 34
  • 56
Javier Manzano
  • 4,761
  • 16
  • 56
  • 86
  • 2
    Possible duplicate of [React Native: Is there a callback function for when your app is closed?](https://stackoverflow.com/questions/38677137/react-native-is-there-a-callback-function-for-when-your-app-is-closed) – bennygenel Oct 10 '17 at 09:11

3 Answers3

78

You can listen to the appState event. From https://facebook.github.io/react-native/docs/appstate.html:

import React, {Component} from 'react'
import {AppState, Text} from 'react-native'

class AppStateExample extends Component {

  state = {
    appState: AppState.currentState
  }

  componentDidMount() {
    AppState.addEventListener('change', this._handleAppStateChange);
  }

  componentWillUnmount() {
    AppState.removeEventListener('change', this._handleAppStateChange);
  }

  _handleAppStateChange = (nextAppState) => {
    if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') {
      console.log('App has come to the foreground!')
    }
    this.setState({appState: nextAppState});
  }

  render() {
    return (
      <Text>Current state is: {this.state.appState}</Text>
    );
  }

}

By the way, this will always say 'Current state is: active', because that is the only state in which the app will be visible for the user.

Fortega
  • 19,463
  • 14
  • 75
  • 113
  • 3
    Wouldn't that just always say 'current state is: active' – Aequitas Feb 28 '19 at 02:11
  • Note that this answer (and the [AppState example](https://reactnative.dev/docs/appstate) on React Native's official docs site) are out of date if you are using hooks. The issue is that the event listener is only added once, so it takes a snapshot of any state at that time and isn't updated afterwards, even if the event listener is called multiple times. See [this](https://stackoverflow.com/questions/53845595/wrong-react-hooks-behaviour-with-event-listener) for a detailed discussion. – starlabs Jun 03 '20 at 19:00
  • iOS application goes from landscape to portrait while going to background and coming to foreground again, thanks to this method now I can switch back to landscape using `react-native-orientation`. – Zeeshan Ahmad Khalil Jun 28 '21 at 06:09
  • This answer shows how to listen for a foreground, not a background. It could be more clear. – Jacob Beauchamp Oct 04 '21 at 17:49
  • removeListener is replaced by remove() in current version. We need to return this remove() in useEffect but how to call remove() in classCmoponent. – CrackerKSR Jul 13 '22 at 14:39
12

You can use the AppState:

App States

  • active - The app is running in the foreground
  • background - The app is running in the background. The user is either in another app or on the home screen
  • inactive - This is a state that occurs when transitioning between foreground & background, and during periods of inactivity such as entering the Multitasking view or in the event of an incoming call
Community
  • 1
  • 1
str
  • 42,689
  • 17
  • 109
  • 127
0

AppState.removeEventListener seems like deprecated, so I did this:

import React from 'react'
import { AppState } from 'react-native'

class AppStateClassComponent extends React.PureComponent {

    constructor(props){
        super(props)

        this.state = {
            appState: ''
        }

        this.onAppStateChange = (nextAppState) => {
            if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') {
                console.log('App has come to the foreground!')
            }
            this.setState({ appState: nextAppState });
        }

        this.app_state = null
    }

    componentDidMount() {
        this.permission_check()
        if(this.app_state === null){
            this.app_state = AppState.addEventListener('change', this.onAppStateChange)
        }
    }

    componentWillUnmount() {
        if(this.app_state !== null){
            this.app_state?.remove()
            this.app_state = null
        }
    }

    render() {
        return (
            <Text>Current state is: {this.state.appState}</Text>
        )
    }
}
nodir.dev
  • 414
  • 4
  • 5