【发布时间】:2019-01-22 13:56:20
【问题描述】:
我认为我的应用程序状态确实存在一些问题。我已经发现this.setState({ ... }) 是一个异步工作的函数。所以,我认为这与我的问题有关。
我的问题是,当我通过 OneSignal 发送推送通知时,我想向我的用户显示一个对话框弹出窗口。 iOS 和 Android 都会收到此推送通知。即使应用程序在 背景,前景或被杀死,甚至没有在后台运行。对于弹出对话框,我正在使用这个包:react-native-popup-dialog
仅当我通过推送通知发送某些键/值对时,此弹出窗口才可见。这些键是:
-
showPopup:true- 为真时显示弹出窗口。如果未设置或不等于 true,则不显示! -
openLink:mydomain.de- 添加带有弹出窗口链接的按钮 -
buttonText:Open in Browser- 将按钮文本设置为链接
注意,额外的 URL 按钮仅在设置了键
openLink和buttonText时才会添加到弹出窗口中。其中没有一个或只设置了一个键,它不显示此按钮。
但是,弹出对话框有时仅在某些情况下显示。我将在下面为您列出:
- 案例 1:应用程序已打开。在这种情况下,弹出窗口会出现在 iOS 和 Android 上。这由
onReceived函数! - 案例 2:应用程序完全关闭(从屏幕上滑出/被杀死)。在这种情况下,弹出窗口显示在 Android 上
设备,但不在 iOS 设备上!这由
onOpened函数处理! - 案例 3:应用程序已打开,现在正在后台运行。在这种情况下,弹出窗口会显示在 iOS 上
设备,但不适用于 Android 设备。这也由
onOpened函数处理!
所以,由于我没有收到错误消息或其他信息,我想我的猜测是正确的,即这个问题是
由于异步 this.setState({ ... }) 函数。
我现在的问题是如何确保在呈现getPopup(...) 方法之前始终设置notification 和visible 的状态。我已经在考虑实现它,所以我调用getPopup(...)带参数的函数。因此,我可以确定在调用方法之前始终设置参数。然而,遗憾的是这是不可能的。因为你在下面看到的类,SuperScreen 类,只是一个由一些子类扩展的类,以捆绑我的代码,如推送通知代码或我在每个子类中需要的一些函数。
另外,我已经尝试将变量添加到我的 SuperClass 状态,例如称为stateSet,在onReceived 或onOpened 的setState({ ... }) 函数完成后设置并使用
if(this.state.stateSet) 在getPopup(...) 函数的第一行。然而,这也是不可能的。原因是当我按下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>
);
}
}
【问题讨论】:
-
发布的代码足够庞大,但缺少 stackoverflow.com/help/mcve 。没有你提到的 stateSet 。不使用 getPopup。考虑提供一种方法来复制问题。像 Stackblitz 这样可以调试的演示会有所帮助。如果问题是异步状态,那么这种情况可能并不特定于 Native,因此组件可能会被存根。
-
我的问题或多或少无法复制,因为您无法在 Stackoverflow 上收到推送通知
标签: reactjs react-native null state setstate