0

这里是 React Native 的初学者,试图将此文档与 AWS Amplify Authentication 结合以实现 React Navigation Authentication Flow,但我似乎无法弄清楚出了什么问题。每当我单击登录按钮时,都会 出现此错误

导航代码(不包括进口):

const NavigationGeneral = () => {

    const [user, setUser] = useState(undefined);

    const checkUser = async () => {
        try {
            const authUser = await Auth.currentAuthenticatedUser({bypassCache: true});
            setUser(authUser);
        } catch (e) {
            setUser(null);
        }
    }

    useEffect(() => {
        checkUser(); 
    }, []);

    if (user === undefined) {
        return (
            <View style = {{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
                <ActivityIndicator />
            </View>
        )
    }

    return (
        <Stack.Navigator screenOptions={{headerShown: false}}>
            {user ? (
                <>
                    <Stack.Screen name = "Login" component = {LoginScreen} />
                    <Stack.Screen name = "SignUp" component = {SignUpScreen} />
                    <Stack.Screen name = "ConfirmEmail" component = {ConfirmEmailScreen} />
                    <Stack.Screen name = "ForgotPassword" component = {ForgotPasswordScreen} />
                    <Stack.Screen name = "NewPassword" component = {NewPasswordScreen} />
                </>
            ): ( 
                <Stack.Screen name = "HomeScreen" component = {HomeTabNavigator} />
            )}
        </Stack.Navigator>
    );
};

//* TAB NAVIGATOR FOR APP SCREENS
const HomeTabNavigator = () => {
    return (
        <Tab.Navigator
            initialRouteName="Home"
            screenOptions={{
                headerShown: false,
                tabBarStyle: {backgroundColor: '#0052cc'},
                tabBarInactiveTintColor: '#fff',
                tabBarActiveTintColor: '#fff',
                tabBarActiveBackgroundColor: '#006600'
            }}>
            <Tab.Screen
                name="Home"
                component={HomeScreen}
                options={{
                tabBarLabel: 'Home',
                tabBarIcon: ({ color, size }) => (
                    <Ionicons name="home-outline" color={'#fff'} size={25} />
                ),
                }}
            />

            <Tab.Screen
                name="Courses"
                component={CourseScreen}
                options={{
                tabBarLabel: 'Courses',
                tabBarIcon: ({ color, size }) => (
                    <Ionicons name="library-outline" color={'#fff'} size={25} />
                ),
                }}
            />

            <Tab.Screen
                name="Profile"
                component={ProfileScreen}
                options={{
                tabBarLabel: 'My Profile',
                tabBarIcon: ({ color, size }) => (
                    <Ionicons name="person-outline" color={'#fff'} size={25} />
                ),
                }}
            />

            <Tab.Screen
                name="Forensic Tools"
                component={ForensicToolsScreen}
                options={{
                tabBarLabel: 'Tools List',
                tabBarIcon: ({ color, size }) => (
                    <Ionicons name="list-outline" color={'#fff'} size={25} />
                ),
                }}
            />

            <Tab.Screen
                name="Leaderboard"
                component={LeaderboardScreen}
                options={{
                tabBarLabel: 'Leaderboard',
                tabBarIcon: ({ color, size }) => (
                    <Ionicons name="podium-outline" color={'#fff'} size={25} />
                ),
                }}
            />

            <Tab.Screen
                name="Settings"
                component={SettingsScreen}
                options={{
                tabBarLabel: 'Settings',
                tabBarIcon: ({ color, size }) => (
                    <Ionicons name="settings-outline" color={'#fff'} size={25} />
                ),
                }}
            />
        </Tab.Navigator>
    );
};

export default NavigationGeneral;

LoginScreen.js代码片段:

const onLoginPressed = async data => {
        if (loading) {
            return;
        }

        setLoading(true);
        try {
            await Auth.signIn(data.username, data.password);
            navigation.navigate("HomeScreen");
            console.log("Login");
        } catch (e) {
            Alert.alert('Oops', e.message);
        }
        setLoading(false);
    };

我知道我不应该使用手动导航navigation.navigate(),而是有条件地定义屏幕。但是每当我navigation.navigate("HomeScreen");从代码中删除时,当我按下登录按钮时什么都没有发生。所以我认为我的代码中的条件有问题NavigationGeneral,我似乎无法找出问题所在。

一些帮助或其他提示将不胜感激,在此先感谢。如果需要更多信息,请告诉我。

4

2 回答 2

0

当您尝试导航到 HomeScreen 时,我假设用户尚未设置为状态,因此名为 HomeScreen 的屏幕尚不存在,因此导航器无处可去。尝试在登录时在 NavigationGeneral 中设置用户,它应该会在不使用 navigation.navigate 的情况下自动重定向事件。

于 2022-02-06T09:46:16.137 回答
0

使用 react-navigation 实现身份验证流程时,不应手动触发导航。成功登录后,用户将被truthy赋值。这意味着导航内部的条件渲染将自动处理它。

此外,如果条件user===undefined不渲染 LoadingIndicator,而是创建一个新的加载状态,并在状态加载为 true 时渲染 LoadingIndicator。

而且我相信它应该!user代替user,因为未经身份验证的用户(user===undefined)会希望看到登录、注册等屏幕。

return (
        <Stack.Navigator screenOptions={{headerShown: false}}>
           // Here it should be !user
            {!user ? (
                <>
                    <Stack.Screen name = "Login" component = {LoginScreen} />
                    <Stack.Screen name = "SignUp" component = {SignUpScreen} />
                    <Stack.Screen name = "ConfirmEmail" component = {ConfirmEmailScreen} />
                    <Stack.Screen name = "ForgotPassword" component = {ForgotPasswordScreen} />
                    <Stack.Screen name = "NewPassword" component = {NewPasswordScreen} />
                </>
            ): ( 
                <Stack.Screen name = "HomeScreen" component = {HomeTabNavigator} />
            )}
        </Stack.Navigator>
    );

  const [checkAuthUserLoading, setCheckAuthUserLoading] = React.useState(false);
  const user = useSelector((state) => state.user); // Retrieve user from redux store. (It can be mobx, zustand or any other state management.)

  const checkUser = async () => {
    try {
      setCheckAuthUserLoading(true);
      const authUser = await Auth.currentAuthenticatedUser({
        bypassCache: true,
      });
      setCheckAuthUserLoading(false);
      dispatch(setAuthUser(user)); // I would suggest to use state management such as redux or mobx instead of storing user in component state
    } catch (e) {
      dispatch(setAuthUserError(e)); // Here you do not need to setUser(undefined) since its already failed and will be stay as undefined
    }
  };

  if (checkAuthUserLoading) {
    return <LoadingIndicator />;
  }
于 2022-02-07T19:00:46.007 回答