Noe Duran
Noe Duran

Reputation: 77

React Native iOS: Check notifications perms memory leak, how to check notifications perms on app launch?

I want to be able to check if the user has notification permissions on or off every time the user opens the app from any state ( if the app was never opened before or the app was in the background etc.) What I have now is checking permissions via PushNotificationIOS.checkPermissions in the render function. However, with that method it keeps on being called and causes a memory leak. Another method I tried was whenever the user wants to be notified (via pressing an icon) the onPress method is called to check the perms but that causes the user to press the icon twice in order for the permission state to be updated.

import {
    PushNotificationIOS,
    AsyncStorage,
    ..
  } from "react-native";


export default class Bell extends React.Component {
  constructor(props) {
    super(props);  
    this.state = {
      isNotifActive: null,
      isBellActive: false,
      alertBody:"",
      fireDate: null,
      LaunchStatus: "",
      ID:'',
      timeSelected: ""
    };
    this.accessKeyNotif = `${this.props.fireDate}-isNotifActive`;

  }

  componentDidMount = () =>{
    this.setState({
        set props to state....
    });
    AsyncStorage.getItem(this.accessKeyNotif).then(value => this.setState({ isNotifActive: JSON.parse(value) }));

  }

  render() {
    PushNotificationIOS.checkPermissions((permissions) => {
      if (permissions.alert) {
        AsyncStorage.setItem(this.accessKeyNotif, JSON.stringify(true)).then(() => {
          this.setState({ isNotifActive: true});

        });
      }
      else{
        AsyncStorage.setItem(this.accessKeyNotif, JSON.stringify(false)).then(() => {
          this.setState({ isNotifActive: false});

        });
      }
    }); 

     return (
      <Ionicons
        name={this.state.isBellActive? "md-notifications":"md-notifications-off"}
        color={"white"}
        size={30}
        style={styles.NotifIcon}
        onPress={() => {
            if(this.state.isNotifActive){
             Make a notification
            }
            else if(!this.state.isNotifActive){
               Cancel Notifications
              }
            }}
        />

    );
  }  
}

The Bell component is called on multiple times (20 times) by another class in order to display the bell.

Upvotes: 1

Views: 676

Answers (1)

Andrew
Andrew

Reputation: 28539

You shouldn't be performing that check in the render method as each setState will cause a re-render, meaning to multiple unnecessary re-renders. It would be better handling this using an AppState listener. The following code will call _handleAppStateChange whenever the app comes into the foreground, goes into the background.

You can import it from react-native like so

import { AppState } from 'react-native'

Then in your component

state = {
  appState: AppState.currentState,  // set the currentState as the appState
};


componentDidMount () {
  // Set the listener
  AppState.addEventListener('change', this._handleAppStateChange);
}

componentWillUnmount () {
  // remove the listener
  AppState.removeEventListener('change', this._handleAppStateChange);
}

_handleAppStateChange = (nextAppState) => {
  if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') {
    // app has come to the foreground
    // perform checks etc here
  }
  // update the appState
  this.setState({ appState: nextAppState });
}

You can read more about it here https://facebook.github.io/react-native/docs/appstate

Upvotes: 1

Related Questions