【问题标题】:RN OneSignal _open EventRN OneSignal _open 事件
【发布时间】:2021-07-14 13:38:25
【问题描述】:

OneSignal on notification open 事件在主屏幕启动后触发,然后导航到所需的屏幕。我想检测应用程序是否在主屏幕呈现之前按通知启动,以便我可以直接导航到第二个屏幕并避免不必要地调用 api。

  • “react-native-onesignal”:“^3.9.3”
  • “反应导航”:“^4.0.0”

代码

   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);
      }
   }, []);

调试

【问题讨论】:

    标签: react-native push-notification react-navigation react-native-onesignal


    【解决方案1】:

    您的问题是如何导航或设置初始屏幕取决于打开的通知负载?

    1) - 根据打开的通知负载设置initial screen

    根据class LifecycleuseEffect在组件输出被渲染后运行,所以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>
        );
    
    }
    

    首先你需要知道

    需要渲染导航器才能处理操作如果您 尝试在不呈现导航器的情况下或在导航器之前导航 完成安装,如果不处理,它将抛出并崩溃您的应用程序。所以 您需要添加额外的检查来决定要做什么,直到您 应用挂载。

    阅读docs

    
    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>
        );
    
    }
    
    

    setTimeoutCommonActions 的引用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-03
      • 1970-01-01
      相关资源
      最近更新 更多