简体   繁体   中英

React Native: Null is not an object - Push notification (OneSignal)

I am facing a problem with my push notifications at the moment.. I am trying to init OneSignal in my repo and I have followed the OneSignal installation guide and double checked it already. Everything is set up correctly!

However, I have two problems which are different on iOS and on Android. There are three ways to receive a push notification:

  • Case 1: The app is opened
  • Case 2: The app has been open, has been closed (not killed) and is still running in the background
  • Case 3: The app is not open and is not running in the background (has been killed/swiped off the screen)

iOS: On my iPhone case 1 and case 2 are working perfectly without any issue. However, in case 3 my application is showing this screen (images attached below).

Android: On Android phones case 1 and 3 is working without any problems but in case 2 the app is not displaying my popup dialog.. But also is not crashing and running!

So, I think, like the iOS screen is telling me, there is somewhere a problem with my state cause it's null . However, in my eyes is still confusing cause exactly this case is working in Android...

However, I am using the functions and EventHandler given in the OneSignal documentation. Also, I am using a library called react-native-popup-dialog to show a popup when sending a push notification. This popup is only visible if I send certain key/value pairs with the push notification. These keys are:

  1. showPopup : true - Displaying the popup when true. If it isn't set or not equals true, it isn't displayed!
  2. openLink : mydomain.de - Adds a button with a link to the popup
  3. buttonText : Open in Browser - Sets the button text to the link

Note, the extra URL button is only added to the popup if key openLink and buttonText is set. Of none of them or only one of the key is set, it isn't displaying this button.

So far so good. So, here is my source code now and I hope you guys can help me out.. trying to debug this since 3 days...

Note, the method getPopup() get's called by several (different) screens which are extending this (SuperScreen) class.

import Dialog, { SlideAnimation, DialogTitle, DialogContent, DialogButton } from "react-native-popup-dialog";
import firebase from "react-native-firebase";
import OneSignal from "react-native-onesignal"

export default class SuperScreen extends Component {
  constructor(props) {
    super(props);
    this.state = {
      pushNotification: null,
      visible: false
    };

    OneSignal.setLogLevel(6, 0);
    OneSignal.init("00000000000000000000000000000000000", {
      kOSSettingsKeyAutoPrompt: true
    });

    OneSignal.inFocusDisplaying(0);
    OneSignal.enableVibrate(true);
    OneSignal.enableSound(true);

    OneSignal.addEventListener("received", this.onReceived);
    OneSignal.addEventListener("opened", this.onOpened);
    OneSignal.addEventListener("ids", this.onIds);
}

  componentWillUnmount() {
    OneSignal.removeEventListener("received", this.onReceived);
    OneSignal.removeEventListener("opened", this.onOpened);
    OneSignal.removeEventListener("ids", this.onIds);
  }

  onReceived = notification => {
    console.log("Notification received: ", notification);

    this.setState({
      pushNotification: notification,
      visible: true
    });

    if (this.state.pushNotification.payload.notificationID != null) {
      firebase.analytics().logEvent("Popup_Link_Button", {
        notificationID: this.state.pushNotification.payload.notificationID,
        clicked: true
      });
    }
  };

  onOpened = openResult => {
    console.log("Message: ", openResult.notification.payload.body);
    console.log("Data: ", openResult.notification.payload.additionalData);
    console.log("isActive: ", openResult.notification.isAppInFocus);
    console.log("openResult: ", openResult);

    this.setState({
      pushNotification: openResult.notification,
      visible: true
    });

    if (this.state.pushNotification.payload.notificationID != null) {
      firebase.analytics().logEvent("Popup_Link_Button", {
        notificationID: this.state.pushNotification.payload.notificationID,
        clicked: true
      });
    }
  };

  onIds = device => {
    console.log("Device info: ", device);
  };

  getPopup() {
    if (
      this.state.pushNotification != null &&
      this.state.pushNotification.payload.additionalData != null &&
      this.state.pushNotification.payload.additionalData.showPopup != null &&
      this.state.pushNotification.payload.additionalData.showPopup == "true"
    ) {
      var actionButtons = null;

      if (
        this.state.pushNotification.payload.additionalData.openLink != null &&
        this.state.pushNotification.payload.additionalData.buttonText != null
      ) {
        actionButtons = [
          <DialogButton
            text="Ok"
            key={0}
            onPress={() => {
              this.setState({ visible: false });
              firebase.analytics().logEvent("Popup_Link_Button", {
                notificationID: this.state.pushNotification.payload
                  .notificationID,
                opened: false
              });
            }}
          />
        ];

        actionButtons.push(
          <DialogButton
            text={this.state.pushNotification.payload.additionalData.buttonText}
            key={1}
            onPress={() => {
              this.openLink(
                this.state.pushNotification.payload.additionalData.openLink
              );
              this.setState({ visible: false });
              firebase.analytics().logEvent("Popup_Link_Button", {
                notificationID: this.state.pushNotification.payload
                  .notificationID,
                link: this.state.pushNotification.payload.additionalData
                  .openLink,
                opened: true
              });
            }}
          />
        );
      } else {
        actionButtons = [
          <DialogButton
            text="Ok"
            key={0}
            onPress={() => {
              this.setState({ visible: false, pushNotification: null });
              firebase.analytics().logEvent("Popup_Link_Button", {
                popupID: this.state.pushNotification.payload.notificationID,
                opened: false
              });
            }}
          />
        ];
      }

      return (
        <Dialog
          visible={this.state.visible == null ? false : this.state.visible}
          dialogTitle={
            <DialogTitle
              title={
                this.state.pushNotification == null
                  ? ""
                  : this.state.pushNotification.payload.title
              }
            />
          }
          dialogAnimation={
            new SlideAnimation({
              slideFrom: "bottom"
            })
          }
          dialogStyle={{ marginLeft: 20, marginRight: 20 }}
          actions={actionButtons}
        >
          <DialogContent>
            <Text />
            <Text>
              {this.state.pushNotification == null
                ? ""
                : this.state.pushNotification.payload.body}
            </Text>
          </DialogContent>
        </Dialog>
      );
    }
  }

My iPhone images:

在此处输入图片说明 在此处输入图片说明

The problem is that you are using a value from state that hasn't been set. Setting state is an asynchronous action so there is no guarantee that it will be set by the time you call it.

You should use the notification object directly and not the one you set to state.

You can learn more about setting state here

https://medium.learnreact.com/setstate-is-asynchronous-52ead919a3f0

Here is an example of what I am meaning.

onReceived = notification => {
    console.log("Notification received: ", notification);

    this.setState({
      pushNotification: notification,
      visible: true
    });
    // use the actual notification object instead of this.state.pushNotification. 
    if (notification.payload.notificationID != null) {
      firebase.analytics().logEvent("Popup_Link_Button", {
        notificationID: notification.payload.notificationID,
        clicked: true
      });
    }
  };

You will also need to update the onOpened function too

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM