按下rnfirebase通知后如何导航到特定屏幕

时间:2020-04-22 14:55:54

标签: android react-native react-native-firebase

我正在使用React Native Firebase,并且在需要时会收到通知,这些通知中有一些数据可导航到特定屏幕。 我使用了Firebase文档来实现该功能,但无法正常运行

这是我使用过的文档Firebase & React-Navigation 我的代码看起来像这样:

const Stack = createStackNavigator();
const Router = () => {
    const navigation = useNavigation();
    const [loading, setLoading] = useState(true);
    const [initialRoute, setInitialRoute] = useState('Splash');

useEffect(() => {
    //fcm
    registerAppWithFCM();
    // checkRNFBPermission();

    const unsubscribe = messaging().onMessage(async remoteMessage => {
        console.log('remote DATAAAAAAAAAAAAAAAAAAAAAAAA : ',remoteMessage.data);
        // switch (remoteMessage.data.screen) {
        //     case 'answer':{
        //         console.log('inside switch condition 1 !!!!!!!!!!!!!');
        //         useNavigation().navigate('Profile');
        //         break;
        //     }
        //     case 'AnswerQuestion':{
        //         console.log('inside switch condition 2 !!!!!!!!!!!!!');
        //         useNavigation().navigate('Profile');
        //         break;
        //     }

        //     default:
        //         break;
        // }
        // Alert.alert('A new FCM message arrived!', JSON.stringify(remoteMessage));
        // const owner = JSON.parse(remoteMessage.data.owner);
        // const user = JSON.parse(remoteMessage.data.user);
        // const picture = JSON.parse(remoteMessage.data.picture);
    });

    // Assume a message-notification contains a "type" property in the data payload of the screen to open
   messaging().onNotificationOpenedApp(remoteMessage => {
      console.log(
        'Notification caused app to open from background state:',
        remoteMessage.notification,
      );
      navigation.navigate('Profile');

    });
    //  Check whether an initial notification is available
    messaging()
    .getInitialNotification()
    .then(remoteMessage => {
      if (remoteMessage) {
        console.log(
          'Notification caused app to open from quit state:',
          remoteMessage.data, //notification
        );
      }
      setLoading(false);
    });

    messaging().setBackgroundMessageHandler(async remoteMessage => {
        console.log('Message handled in the background!', remoteMessage);
    });

    return unsubscribe;
    //fcm
}, []);

//fcm
checkRNFBPermission = async() => {
    const enabled = await messaging().hasPermission();
    if(enabled){
        messaging()
        .getToken()
        .then(token => {
            // console.log('deviceeeee fcm token ------> ', token);
        });    
    }else{
        requestUserPermission();
    }
}
registerAppWithFCM = async() => {
    await messaging().registerDeviceForRemoteMessages();
}
requestUserPermission = async() =>  {
    const settings = await messaging().requestPermission();
    if (settings) {
        console.log('Permission settings:', settings);
    }
}
//fcm

renderLoading = () => (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center'  }}>
        <Text>Domanda</Text>
        <ActivityIndicator size='large' color={colors.darkerTeal} />
    </View>
);

//firebase
if (loading) {
    return null;
}
//firebase
return(
    <Provider store={store}>
        <PersistGate persistor={persistor} loading={this.renderLoading()}>
            <Root>
                <NavigationContainer>
                    <Stack.Navigator initialRouteName={initialRoute} headerMode="none">
                        <Stack.Screen name="Splash" component={Splash} />
                        <Stack.Screen name="Login" component={Login} />
                        <Stack.Screen name="Main" component={Main} />
                        <Stack.Screen name="AppIntro" component={AppIntro} />
                        <Stack.Screen name="Tags" component={Tags} />
                        <Stack.Screen name="Answers" component={Answers} />
                        <Stack.Screen name="Profile" component={Profile} />
                        <Stack.Screen name="EditInfo" component={EditInfo} />
                        <Stack.Screen name="ChangePassword" component={ChangePassword} />
                        <Stack.Screen name="AnswerQuestion" component={AnswerQuestion} />
                        <Stack.Screen name="ContactUs" component={ContactUs} />
                    </Stack.Navigator>
                </NavigationContainer>
            </Root>
        </PersistGate>
    </Provider>
)

};

export default Router;

但是当我添加usenavigation并想要使用它时,它将引发此错误: 错误:我们找不到导航对象。您的组件是否在导航器的屏幕内?

enter image description here

我无法使用navigation.navigate('Profile');导航到特定屏幕。

2 个答案:

答案 0 :(得分:1)

您正在App.js中收到消息,StackNavigator之外的消息。 您可以使用ref来使用导航器的导航属性

在您的app.js顶部定义导航器

var navigator = null;

然后将引用添加到导航器

<Stack.Navigator 
  initialRouteName={initialRoute}
  headerMode="none"
   ref={nav => {
     navigator = nav;
   }}
 >

并将您的路线推入接收方法

navigator.dispatch(
  NavigationActions.navigate({
     routeName: 'theRoute',
       params: {},
   }),
 );

答案 1 :(得分:0)

挣扎了4个小时...

  1. 某些组件在其中,可以进行导航(在我的情况下为“主屏幕”)

    //上次导入

     import { ScrollWrapper } from './styles'
    
     export const navigationRef = React.createRef();
         export const isReadyRef = React.createRef();
         export function navigate(name, params) {
           if (isReadyRef.current && navigationRef.current) {
             // Perform navigation if the app has mounted
             navigationRef.current.navigate(name, params);
           } else {
             console.log(' else [ELSE] --- ')
             // You can decide what to do if the app hasn't mounted
             // You can ignore this, or add these actions to a queue you can call later
           }
         }
    
     // component start
     export const SocialHomeScreen = () => {...
    
  2. 在App.js中

从'./screens/PeopleAroundYou/index'导入{导航,navigationRef,isReadyRef}

// ....导航器

const App = () => {
  const [isAuth, setIsAuth] = useState(false)

  AsyncStorage.getItem('pushNotify').then(value => {
    console.log('value --- ', value)
    console.log('JSON.parse(value) --- ', JSON.parse(value))
  }).catch(error => {
    console.log('error --- ', error)
  })

  // foreground message arrived
  useEffect(() => {
    return messaging().onMessage(async remoteMessage => {
      const { data, notification } = remoteMessage
      if (data.type === 'activity-check-in') {

        console.log(' A new FCM message arrived! --- ')
        console.log('data --- ', data)
        console.log('notification --- ', notification)
        console.log(' navigator --- ',  navigate)
        console.log('navigationRef.current.getRootState() --- ', navigationRef.current.getRootState())
        

        switch (data.category) {
          case 'fitness':
            // navigate to nested screen
            navigate(routes.Fitness, {
              screen: routes.ActivityDetails,
              params: { activityId: data.eventId}
            })
            break
          case 'companionship':
            navigate(routes.Companionships, {
              screen: routes.ActivityDetails,
              params: { activityId: data.eventId}
            })
            break
          case 'volunteering':
            navigate(routes.Volunteering, {
              screen: routes.ActivityDetails,
              params: { activityId: data.eventId}
            })
            break
          case 'wellbeing':
            navigate(routes.Wellbeing, {
              screen: routes.ActivityDetails,
              params: { activityId: data.eventId}
            })
            break
          
        }

      }
    })
  }, [])


  useEffect(() => {
    SplashScreen.hide()

    fcmService.registerAppWithFCM()
    fcmService.register(onRegister, onNotification, onOpenNotification)
    localNotificationService.configure(onOpenNotification)

    function onRegister(token) {
      console.log('[App] onRegister: ', token)
    }

    function onNotification(notify) {
      console.log('[App] onNotification: ', notify)
      const options = {
        soundName: 'default',
        playSound: true, //,
        // largeIcon: 'ic_launcher', // add icon large for Android (Link: app/src/main/mipmap)
        // smallIcon: 'ic_launcher' // add icon small for Android (Link: app/src/main/mipmap)
      }
      localNotificationService.showNotification(
        0,
        notify.title,
        notify.body,
        notify,
        options,
      )
    }

    function onOpenNotification(notify) {
      console.log('[App] onOpenNotification: ', notify)
      Alert.alert('Open Notification: ' + notify.body)
    }

    return () => {
      console.log('[App] unRegister')
      fcmService.unRegister()
      localNotificationService.unregister()
    }
  }, [])

  const authContext = useMemo(() => {
    return {
      login: () => {
        setIsAuth(true)
      },
      logout: () => {
        setIsAuth(false)
      },
    }
  })

  return (
    <AuthContext.Provider value={authContext}>
      <ThemeProvider theme={theme}>
        <NavigationContainer
          ref={navigationRef}
          onReady={() => {
            isReadyRef.current = true
          }}
          linking={linking}
          fallback={
            <View style={{ justifyContent: 'center', alignItems: 'center' }}>
              <Loader loading size='large' color='#61A5C8'/>
            </View>
          }
        >
          {isAuth ? <AuthorizedTabs /> : <NonAuthorizedStack/>}
        </NavigationContainer>
      </ThemeProvider>
    </AuthContext.Provider>
  )
}