Reputation: 738
I have a component which fetch a request in every 30 seconds interval, it's working fine as expected. But I want when app goes in background state the request will stop and when app in foreground the request will start and vise-versa. Is there is any solution to do this.
Here is my component file.
Notifications.js
/**
* Notification Button
*/
import React from "react";
import { View, TouchableWithoutFeedback, Text } from "react-native";
import { connect } from "react-redux";
import Icon from 'react-native-vector-icons/MaterialIcons';
// styles
import styles from "./Styles";
// global styles
import globalStyles from "BkProvider/src/styles/global";
import { colors } from "BkProvider/src/styles/base";
// root navigator
import { rootNavigator } from "BkProvider/src/screens/DashboardGroup";
// strings
import strings from "BkProvider/src/strings";
// actions
import { getSystemAlerts, seeAllSystemAlertLogs, stopNotificationTick } from "BkProvider/src/actions";
// Navigation constants
import NavigationConstants from "BkProvider/src/constants/NavigationConstants";
const { posRelative } = globalStyles;
class NotificationButton extends React.Component {
componentDidMount() {
this.props.getSystemAlerts();
}
componentWillUnmount() {
stopNotificationTick();
}
/**
* Function to open system alerts popup
*/
openSystemAlerts() {
this.props.seeAllSystemAlertLogs(this.props.unseenAlertLogIdsArray);
rootNavigator.push({
screen: NavigationConstants.SYSTEM_ALERTS_LISTING,
title: strings.allNotifications,
backButtonTitle: ''
});
}
render() {
const { unseenAlertLogIdsArray } = this.props;
return (
<TouchableWithoutFeedback onPress={this.openSystemAlerts.bind(this)}>
<View style={styles.button}>
<View style={[posRelative]}>
<Icon
name="notifications-none"
size={27}
color={colors.white}
/>
{(unseenAlertLogIdsArray && unseenAlertLogIdsArray.length > 0) &&
<Text style={styles.badge}>{unseenAlertLogIdsArray.length}</Text>
}
</View>
</View>
</TouchableWithoutFeedback>
);
}
}
const mapStateToProps = ({ systemAlerts }) => {
const { unseenAlertLogIdsArray } = systemAlerts;
return { unseenAlertLogIdsArray }
}
export default connect(mapStateToProps, {
getSystemAlerts,
seeAllSystemAlertLogs
})(NotificationButton);
Actions.js
/**
* System Alerts Actions
*/
import Toast from "react-native-simple-toast";
import { NetInfo } from "react-native";
// action types
import {
GET_SYSTEM_ALERTS,
SEE_ALL_SYSTEM_ALERT_LOGS
} from "BkProvider/src/actions/actionTypes";
// helpers methods
import { getUserId } from "./AppInitializer";
// webservice config
import WebServiceConfig, { APITypes } from "../webservice/WebServiceConfig";
import WebService from "../webservice/WebService";
import APINames from "../webservice/APINames";
let timer = null;
let globalDispatch;
let webServiceObject
/**
* Function To Get System Alerts
*/
export const getSystemAlerts = () => (dispatch) => {
clearInterval(timer);
globalDispatch = dispatch;
let apiConfig = new WebServiceConfig(APINames.LoadSystemAlertLogs),
httpParams = {
'page': "",
'limit': "",
'role': 'provider',
'uid': getUserId()
}
webServiceObject = new WebService(onResultCallback)
.addPostParameterObject(httpParams)
.addServiceConfiguration(apiConfig)
timer = setInterval(() => notificationsTick(), 15000);
notificationsTick();
}
/**
* API Response Callback Handler
*/
const onResultCallback = (webServiceResultObj) => {
if (webServiceResultObj.isSuccess && webServiceResultObj.response != null) {
if (webServiceResultObj.response.api_status === 1) {
if (globalDispatch) {
globalDispatch({ type: GET_SYSTEM_ALERTS, payload: webServiceResultObj.response.data });
}
}
} else {
if (webServiceResultObj.shouldShowErrorMessage)
Toast.show(webServiceResultObj.errorMessage)
}
}
/**
* System Alerts Notification Ticks
*/
const notificationsTick = () => {
NetInfo.isConnected.fetch().then(isConnected => {
if (isConnected) {
if (webServiceObject)
webServiceObject.execute();
}
})
}
/**
* Function To Clear The Interval Of System Alerts Api
*/
export const stopNotificationTick = () => {
clearInterval(timer);
}
/**
* Function To See All System Alerts Logs
*/
export const seeAllSystemAlertLogs = (unseenAlertLogIdsArray) => (dispatch) => {
if (unseenAlertLogIdsArray) {
let apiConfig = new WebServiceConfig(APINames.SeeAllSystemAlertLogs)
.setAPIType(APITypes.POST);
// params
let params = {
role: "provider",
uid: getUserId(),
unseen_log_ids: unseenAlertLogIdsArray
}
dispatch({ type: SEE_ALL_SYSTEM_ALERT_LOGS }); // dispatch an action to see all system alert logs
new WebService()
.addPostParameterObject(JSON.stringify(params))
.addServiceConfiguration(apiConfig)
.execute()
}
}
Upvotes: 1
Views: 3776
Reputation: 11724
Just check the AppState when notificationsTick gets called.
if(AppState.currentState === "active"){
notificationsTick();
}
Note that JS timers might not get called when your app is in background - From my own experience, on iOS, click the home button, touch power button to enter sleep mode, application Javascript gets frozen in 10 seconds. And they might get called when your app gets back in foreground... You should test that
A more robust implementation would keep a reference on the timer, and cancel it when app goes into background.
Upvotes: 2
Reputation: 577
There is a React native API for that. https://facebook.github.io/react-native/docs/appstate
This would let you check if the app is in background or foreground, and then you can either cancel the request, or continue.
Basic Usage example from their 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>
);
}
}
This console logs the current state of the app, so you would need to add this AppState to your state and do whatever you need.
Upvotes: 0
Reputation: 11
You should use App state for this case here is the sample code that i used
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>
);
}
}
Upvotes: 0