React Native:state有时为null-setState异步工作



我想我的应用程序的状态确实有一些问题。我已经知道this.setState({ ... })是一个异步工作的函数。。所以,我认为这与我的问题有关。

我的问题是,当我通过OneSignal发送推送通知时,我想向用户显示一个弹出对话框。iOS和Android都会收到此推送通知。即使应用程序在背景,前景或被杀,甚至没有在背景中运行。对于弹出对话框,我使用这个包:反应本地弹出对话框

只有当我发送带有推送通知的特定键/值对时,此弹出窗口才可见。这些密钥是:

  1. showPopup:true-当为true时显示弹出窗口。如果未设置或不等于true,则不会显示
  2. openLink:mydomain.de-添加一个带有弹出窗口链接的按钮
  3. buttonText:Open in Browser-将按钮文本设置为链接

注意,只有在设置了openLinkbuttonText键的情况下,才会将额外的URL按钮添加到弹出窗口中。其中没有一个或只设置了一个键,它不会显示此按钮。

但是,弹出对话框仅在某些情况下显示。我将在下面为您列出它们:

  1. 情况1:应用程序已打开。在这种情况下,弹出窗口会显示在iOS和Android上。这由onReceived功能
  2. 案例2:应用程序完全关闭(从屏幕上滑下/关闭)。在这种情况下,弹出窗口显示在Android上设备,但不在iOS设备上!这由onOpened函数处理
  3. 案例3:该应用程序已打开,目前正在后台运行。在这种情况下,弹出窗口会显示在iOS上设备,但不在Android设备上。这也由onOpened函数处理

所以,由于我没有收到错误消息或其他什么,我想我的猜测是正确的,这个问题是由于异步CCD_ 13功能。

我现在的问题是,在渲染getPopup(...)方法之前,如何确保始终设置notificationvisible的状态。。我已经在考虑实现它,以便用参数调用getPopup(...)函数。因此,我可以确定参数总是在调用该方法之前设置好的。然而,遗憾的是,这是不可能的。因为你在下面看到的类,SuperScreen类,只是一个被一些子类扩展的类,用来捆绑我的代码,比如推送通知代码或我在每个子类中需要的一些函数。

此外,我已经尝试向我的SuperClass状态添加一个变量,例如stateSet,它在onReceivedonOpenedsetState({ ... })函数完成后设置,并用CCD_ 25函数的第一行中的CCD_。然而,这也是不可能的。原因是当我按下Ok或链接按钮时,我的弹出窗口不再关闭。

如果你们对如何解决这个问题有任何想法,我真的很感激!这是我的代码:

export default class SuperScreen extends Component {
constructor(props) {
super(props);
this.state = {
pushNotification: null,
visible: false
};
OneSignal.init("00000000", {
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 => {
//App is opened!
console.log("Notification received: ", notification);
this.setState({
pushNotification: notification,
visible: true
});
if (notification.payload.notificationID != null) {
firebase.analytics().logEvent("Popup_Link_Button", {
notificationID: notification.payload.notificationID,
clicked: true
});
}
};
onOpened = openResult => {
//App either is closed or running in background
//Android:  Closed: Showing       Background: Not Showing
//iOS:      Closed: Not Showing   Background: Showing)
console.log("openResult: ", openResult);
this.setState({
pushNotification: openResult.notification,
visible: true
});
if (openResult.notification.payload.notificationID != null) {
firebase.analytics().logEvent("Popup_Link_Button", {
notificationID: openResult.notification.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 });
firebase.analytics().logEvent("Popup_Link_Button", {
popupID: this.state.pushNotification.payload.notificationID,
opened: false
});
}}
/>
];
}
return (
<Dialog
visible={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>
);
}
}

您可以向setState添加回调,以确保代码在设置状态后运行:

this.setState().then({ //Do something here. })

异步使用asyncawait

onReceived = async (notification) => {
//App is opened!
console.log("Notification received: ", notification);
await this.setState({ // It will wait until finish setState. 
pushNotification: notification,
visible: true
}); 
if (notification.payload.notificationID != null) {
firebase.analytics().logEvent("Popup_Link_Button", {
notificationID: notification.payload.notificationID,
clicked: true
});
}
};

您可以在setState中使用回调!,我一个月前就从中吸取了教训,从那以后一直很有用。查看本文,您可以将函数作为回调传递;)

this.setState(
{ pushNotification: notification,
visible: true }, () => {this.getPopup()}) //this.getPopup it's the second parameter, a callback

查看文章,它很短,将有助于

相关内容

  • 没有找到相关文章

最新更新