React Native stop animation when leaving the app - react-native

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

Related

how to change Class component to functional component in react native

I am new to react native. how To change above code which is in class component to functional component. please help. thanks
import { BackHandler } from 'react-native';
constructor(props) {
super(props)
this.handleBackButtonClick = this.handleBackButtonClick.bind(this);
}
componentWillMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButtonClick);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButtonClick);
}
handleBackButtonClick() {
this.props.navigation.navigate("Browse");
return true;
}
use can use useEffect hook to get the functionality in useEffect the return function acts componentWillUnmount
code:
function handleBackButtonClick() {
navigation.goBack(null);
return true;
}
useEffect(() => {
BackHandler.addEventListener('hardwareBackPress',handleBackButtonClick);
return () => {
BackHandler.removeEventListener('hardwareBackPress',handleBackButtonClick);
}
}, [])
I recommend you to watch the documentary of useEffect (Hooks). For now, this code would be the conversion from Class to Functional. As you notice we can write unmount and mount functions inside the useEffect
import { BackHandler } from "react-native";
const MyNewFunctionalComponent = ({ navigation }) => {
useEffect(() => {
function handleBackButtonBlick() {
navigation.goBack();
}
BackHandler.addEventListener('hardwareBackPress', handleBackButtonClick);
return function cleanup() {
BackHandler.removeEventListener('hardwareBackPress', handleBackButtonClick);
};
}, [])
return (
// Display what you want here
null
)
}

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

Device Physical button click handling

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

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