Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to listen App launch and close in React Native?

I need to track some logs event(only once) when App launch and close.

First I do this in Home screen componentDiMount(), but it will be instantiated several times in some case, causing repetitive launch event log.

=============== Edit =================

AppState can only listen background and active event.

When closing app on Android (press back key or close in recents app menu), it actually back to background. It takes the app back to active from background when reopen the app. Which is the same as toggle app between background and active(not close)

So I can't determine whether it is first launch or toggling app status using AppState

like image 283
junlin Avatar asked Mar 13 '18 02:03

junlin


People also ask

How do you detect app is closed in React Native?

With @react-native-community/hooks you can use the useAppState hook to check the app state. When you close the app, it gets a state of unknown once you open it back. When is in background, it says background' or 'inactive'.

What is use of AppState in React Native?

In React Native, AppState represents the current state of the app — i.e., whether the app is in the foreground or background. AppState is useful for collecting data on app usage — for example, the time a user spends in the app before putting it in the background or closing the app.

How do I make React Native apps run in the background?

Currently, there is, unfortunately, no support for background tasks of any kind. The feature you are referring to would be a background timer. Such a timer is this product pain (a feature request) for react native, you may upvote it to show an increased demand for this feature.


2 Answers

On App Launch

In general, useEffect with an empty dependency array is what you're looking for.

In React Native, code can be running when app state is not active, but useEffect with an empty dependency array will be running on first app launch.

If you're using dependency values, you can use useRef to track if it's handled in first app launch.

const onLaunchRef = React.useRef<boolean>();

useEffect(() => {
  if (onLaunchRef.current) {
    return;
  }
  doSomething(state1, state2);
  onLaunchRef.current = true;
}, [state1, state2]);

You can combine this with useAppState:

import { useAppState } from '@react-native-community/hooks'

const onLaunchRef = React.useRef<boolean>();
const appState = useAppState();

useEffect(() => {
  if (onLaunchRef.current) {
    return;
  }
  if (appState !== 'active') {
    return;
  }
  doSomething(state1, state2);
  onLaunchRef.current = true;
}, [state1, state2, appState]);

On App Close

You can use the following:

useEffect(() => {
  return () => {
    doSomething(state1, state2);
  };
}, [state1, state2]);

Or use useAppState:

const appState = useAppState();
useEffect(() => {
  if (appState !== 'active') {
    doSomething();
  }
}, [appState]);

However, actual close event does not exist in React Native. This is somewhat tricky problem to handle.

like image 92
glinda93 Avatar answered Oct 16 '22 21:10

glinda93


Note: Following answer was written when OP didn't edit the question to add info about the limitations of AppState.

Using AppState.

From Official Docs:

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>
    );
  }

}
like image 21
hasn Avatar answered Oct 16 '22 21:10

hasn