在通知打开事件时,OneSignal在主屏幕启动后触发,然后导航到所需的屏幕。我想检测应用程序是否是在主屏幕呈现之前按下通知启动的,这样我就可以直接导航到第二个屏幕,避免不必要地调用apis。
码
const _opened = openResult => {
const { additionalData, body } = openResult.notification.payload;
// how to navigate or set the initial screen depending on the payload
}
useEffect(() => {
onesignal.init();
onesignal.addEventListener('received', _received);
onesignal.addEventListener('opened', _opened);
SplashScreen.hide();
return () => {
// unsubscriber
onesignal.removeEventListener('received', _received);
onesignal.removeEventListener('opened', _opened);
}
}, []);Debug

发布于 2021-07-18 22:44:50
您的问题是如何根据打开的通知有效载荷来导航或设置初始屏幕?
1) -根据打开的通知有效载荷设置initial screen。
根据类生命周期 useEffect,在呈现组件输出之后运行,所以useEffect中的侦听器直到组件数量达到为止才会侦听,这是主屏幕中日志显示在useEffect日志之前的原因,请参见以下解释。
//this the problem (NavigationContainer called before useEffect).
function App() {
useEffect(() => {}); //called second.
return <NavigationContainer>; //called first.
}
//this the solution (useEffect called Before NavigationContainer).
function App() {
const [ready, setReady] = useState(false);
//called second.
useEffect(() => {
//listen here
setReady(true);
SplashScreen.hide();
});
//called first
//no function or apis run before useEffect here it just view.
if(!ready) return <></>;// or <LoadingView/>
//called third.
return <NavigationContainer>;
}你的代码可能是这样的。
function App() {
const [ready, setReady] = useState(false);
const openedNotificationRef = useRef(null);
const _opened = openResult => {
openedNotificationRef.current = openResult.notification.payload;
}
const getInitialRouteName = () => {
if (openedNotificationRef.current) {
return "second"; //or what you want depending on the notification.
}
return "home";
}
useEffect(() => {
onesignal.addEventListener('opened', _opened);
//setTimeout(fn, 0) mean function cannot run until the stack on the main thread is empty.
//this ensure _opened is executed if app is opened from notification
setTimeout(() => {
setReady(true);
}, 0)
});
if(!ready) return <LoadingView/>
return (
<NavigationContainer initialRouteName={getInitialRouteName()}>
</NavigationContainer>
);
}2) - navigate取决于打开的通知有效载荷。
首先你要知道
如果您试图在不呈现导航器的情况下导航,或者在导航器完成安装之前,它将抛出并使您的应用程序崩溃(如果不处理),则需要呈现导航器以处理操作。因此,您需要添加一个额外的检查,以决定做什么,直到您的应用程序挂载。
读取文档
function App() {
const navigationRef = React.useRef(null);
const openedNotificationRef = useRef(null);
const _opened = openResult => {
openedNotificationRef.current = openResult.notification.payload;
//remove loading screen and start with what you want.
const routes = [
{name : 'home'}, //recommended add this to handle navigation go back
{name : 'orders'}, //recommended add this to handle navigation go back
{name : 'order', params : {id : payload.id}},
]
navigationRef.current.dispatch(
CommonActions.reset({
routes : routes,
index: routes.length - 1,
})
)
}
useEffect(() => {
//don't subscribe to `opened` here
//unsubscribe
return () => {
onesignal.removeEventListener('opened', _opened);
}
}, []);
//subscribe to `opened` after navigation is ready to can use navigate
const onReady = () => {
onesignal.addEventListener('opened', _opened);
//setTimeout(fn, 0) mean function cannot run until the stack on the main thread is empty.
//this ensure _opened is executed if app is opened from notification
setTimeout(() => {
if (!openedNotificationRef.current) {
//remove loading screen and start with home
navigationRef.current.dispatch(
CommonActions.reset({
routes : [{name : 'home'}],
index: 0,
})
)
}
}, 0)
};
return (
<NavigationContainer
ref={navigationRef}
onReady={onReady}
initialRouteName={"justLoadingScreen"}>
</NavigationContainer>
);
}setTimeout,CommonActions参考文献。
https://stackoverflow.com/questions/68379185
复制相似问题