Device Physical button click handling - react-native

Is it possible to get a callback on click of home and recent apps buttons of the device?
Although we can handle back, I want to handle the others too I searched but couldn't find any way for this one.
Thanks in Advance

We have no callback for this event, but you can use the lifecycle methods to detect when user click button home
Below is an example from App state
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(/active/) &&
nextAppState === 'background'
) {
console.log('user click button home');
}
this.setState({appState: nextAppState});
};
render() {
return <Text>Current state is: {this.state.appState}</Text>;
}
}

Related

React Native App - swipe right means all componenets unmount....can this be stopped?

With Android...when you swipe right on an app, it will unmount all components and cease all app operations. First component to be unmounted appears to be the parent componenet (normally named app.js).....please correct me if Im wrong on this.
When this happens..I know the componentWillUnmount event fires as I added the code below that logs to the console.
componentWillUnmount() {
console.log('app.js....componentWillUnmount');
}
My question is whether I can add some extra code within componentWillUnmount that could Alert the user "are you sure you want to quit app?"....and give them an option so say "no" and keep the app live
The BackHandler API description on the React-Native official docs has the example for the same use case. You can take a look at the given example code snippet on the official docs and pick the example with functional or class based component as per your choice.
You can place that code at the top level component like App.js or Routes.js.
Another approach with the autohide toast can be:
Using functional component
import React, {useEffect, useRef} from 'react';
import {Text, SafeAreaView, BackHandler, ToastAndroid} from 'react-native';
export default function App() {
const doubleBackToExitPressedOnce = useRef(false);
useEffect(() => {
const backAction = () => {
if (doubleBackToExitPressedOnce.current) {
BackHandler.exitApp();
return true;
}
ToastAndroid.show('Press back again to exit', ToastAndroid.SHORT);
doubleBackToExitPressedOnce.current = true;
setTimeout(() => {
doubleBackToExitPressedOnce.current = false;
}, 2000);
return true;
};
const backHandler = BackHandler.addEventListener(
'hardwareBackPress',
backAction,
);
return () => backHandler.remove();
}, []);
return (
<SafeAreaView>
<Text>Hello world!</Text>
</SafeAreaView>
);
}
Using class component:
import React, {Component} from 'react';
import {SafeAreaView, Text, BackHandler, ToastAndroid} from 'react-native';
export default class App extends Component {
backAction = () => {
if (this.doubleBackToExitPressedOnce) {
BackHandler.exitApp();
}
ToastAndroid.show('Press back again to exit', ToastAndroid.SHORT);
this.doubleBackToExitPressedOnce = true;
setTimeout(() => {
this.doubleBackToExitPressedOnce = false;
}, 2000);
return true;
};
componentDidMount() {
this.doubleBackToExitPressedOnce = false;
this.backHandler = BackHandler.addEventListener(
'hardwareBackPress',
this.backAction,
);
}
componentWillUnmount() {
this.backHandler.remove();
}
render() {
return (
<SafeAreaView>
<Text>Hello world!</Text>
</SafeAreaView>
);
}
}

react-native deeplink only works one time

I'm using deep linking in react-native in order to redirect the user on a specific youtube channel whenever he clicks on the button.
It's working well but when the user came back on the application using the back button, it's displaying a blank screen and I'm not able to redirect the user to the youtube channel anymore.
How can I make the deeplinking works every time ? Thanks !
import React from 'react';
import { View, Text, Linking, Platform } from 'react-native';
class ChaineYT extends React.Component {
state = {
isLoading:false,
isLinked: false
}
componentDidMount = () => {
Linking.openURL('http://www.youtube.com/channel/UC1UpcbyFVTZTDrvdjNmSzSg');
this.setState({isLoading:true, isLinked:true});
if(this.state.isLoading && this.state.isLinked){
this.props.navigation.navigate('Acceuil')
}
}
render() {
return (
<View>
</View>
)
}
}
export default ChaineYT
How can I manage the youtube app in background ?
You will have to use AppState for it
import React from 'react';
import { View, Text, Linking, Platform, AppState } from 'react-native';
class ChaineYT extends React.Component {
state = {
isLoading:false,
isLinked: false,
appState: AppState.currentState,
}
componentDidMount = () => {
Linking.openURL('http://www.youtube.com/channel/UC1UpcbyFVTZTDrvdjNmSzSg');
this.setState({isLoading:true, isLinked:true});
AppState.addEventListener('change', this._handleAppStateChange);
}
componentWillUnmount() {
AppState.removeEventListener('change', this._handleAppStateChange);
}
_handleAppStateChange = (nextAppState) => {
if (
this.state.appState.match(/inactive|background/) &&
nextAppState === 'active'
) {
if(this.state.isLoading && this.state. isLinked){
this.props.navigation.navigate('Acceuil')
}
}
this.setState({appState: nextAppState});
};
render() {
return (
<View>
</View>
)
}
}
export default ChaineYT
Deeplink with react-navigation v5 in react-native is explained from scratch here

React Native - How to detect home button is pressed or not?

I can know when the scene is on screen using following code:
this.subs = [
this.props.navigation.addListener('didFocus', this.loadOfflineData)
];
But , if I want to detect when scene is out of focus. I 'm wondering what should I do .
Basically I want to detect if the user press home button and then I want to perform some action.
Any suggestions.
You can use AppState to know when an app is put into the background.
AppState can tell you if the app is in the foreground or background, and notify you when the state changes.
Here is a simple example of using AppState:
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!');
} else {
console.log('App has gone to the background!');
// start your background task here
}
this.setState({appState: nextAppState});
};
render() {
return <Text>Current state is: {this.state.appState}</Text>;
}
}
I've done this with android and java using the android lifecycle. This should work in React Native (see EDIT down below). the developer.android.com forum: this page
In short:
onCreate(): a user opens your app for the first time
onStart(): app restarts
onResume(): a user opens your app while it was active in the background
onPause(): app goes out of focus
onStop(): app is no longer visible
onDestroy(): activity will be destroyed
In your case you should use onPause()
So a little code snippet for in java:
#Override
public void onPause() {
super.onPause();
//do something
}
EDIT:
This answer tells you how to detect onPause and onResume in Reacte Native.
Code in that answer:
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>
);
}
}

React Native stop animation when leaving the app

I have an Animated.timing and I want to stop it when the user navigate to another app, is this possible?
you can use AppState like this:
import React, {Component} from "react"
import {AppState, View} from "react-native"
class YourClass extends Component {
state = {
appState: AppState.currentState
}
componentDidMount() {
//add a listener here
AppState.addEventListener("change", this._handleAppStateChange);
}
componentWillUnmount() {
// remember add this line
AppState.removeEventListener("change", this._handleAppStateChange);
}
_handleAppStateChange = (nextAppState) => {
if (this.state.appState.match(/inactive|background/) && nextAppState === "active"){
console.log("App has come to the foreground!")
}else{
//here you can call stop animation function
}
this.setState({appState: nextAppState});
}
render() {
return (
<Text>Current state is: {this.state.appState}</Text>
);
}
}

React-Native : change state when app is in background

I create a simple app that using React Native AppState:
import React, {Component} from 'react'
import {AppState, Text , View} from 'react-native'
export default class AppStateExample extends React.Component {
constructor(props){
super(props);
this.state = {
name:'not change'
}
}
componentDidMount() {
AppState.addEventListener('change', this._handleAppStateChange);
}
componentWillUnmount() {
AppState.removeEventListener('change', this._handleAppStateChange);
}
_handleAppStateChange = (nextAppState) => {
if(AppState.currentState=='background'){
console.log('background mode');
this.setState({name:'back'});
}
if(AppState.currentState =='active'){
//...
}
};
render() {
return (
<View>
<Text>State Name : {this.state.name}</Text>
</View>
);
}
}
And when I try switch app from foreground to background and then background to foreground console.log('background mode'); work very well and console
print 'background mode'
BUT
The this.setState({name:'back'}); not working and I see 'not change' text in view
Actually, based on React Native Docs on AppState change for Functional Component I prefer to write code like below:
import { useRef, useState, useEffect } from "react";
import { AppState } from "react-native";
const AppStateManager = () => {
const appState = useRef(AppState.currentState);
const [appStateVisible, setAppStateVisible] = useState(appState.current);
useEffect(() => {
AppState.addEventListener("change", handleAppStateChange);
return () => {
AppState.removeEventListener("change", handleAppStateChange);
};
}, []);
const handleAppStateChange = (nextAppState) => {
if (
appState.current.match(/inactive|background/) &&
nextAppState === "active"
) {
console.log("App has come to the foreground!");
}
appState.current = nextAppState;
setAppStateVisible(appState.current);
console.log("AppState", appState.current);
};
return null;
};
export default AppStateManager;
Surely, we can use this component in the root of the project just like a React Component:
~~~
<App>
~~
<AppStateManager />
~~
.
.
.
It is because, AppState.addEventListener('change', this._handleAppStateChange); is too late to register.
You probably want to listen AppState the first thing in your app before main components get loaded and pass down the values probably by your state management library
I would go for a switch that wrap all endPoint
note: to get appState status AppState.currentState
this.state = {
appState: AppState.currentState
// https://facebook.github.io/react-native/docs/appstate.html
};
componentWillMount() {
AppState.addEventListener('change', () => this._handleAppStateChange());
};
componentWillUnmount() {
AppState.removeEventListener('change', () => this._handleAppStateChange());
}
_handleAppStateChange() {
// https://facebook.github.io/react-native/docs/appstate.html
const {
appState
} = this.state;
console.warn({
appState
})
this.fetchData().catch(error => error);
switch (appState) {
case 'active': //The app is running in the foreground
this.onStart();
break;
case 'background': // The app is running in the background. The user is either
this.onEnd();
console.warn('background');
break;
case 'inactive':
// The app transitioning between foreground & background or entering the Multitasking view or in the event of an incoming call
console.warn('Inactive');
break;
default:
console.warn('_handleAppStateChange default');
}
}