javascript - 如何在 React Native 中登录和注销后在 2 个不同的导航器之间导航

标签 javascript reactjs react-native

我对 react native 有点陌生,在我的应用程序的 react native 屏幕中登录和注销后,我很难在两个不同的选项卡导航器之间导航,这些屏幕都使用功能组件屏幕

有人可以建议我如何做到这一点吗?

在我的导航目​​录(处理导航流程)中,我有 2 个文件 index.js 和 main.js

  1. 导航/index.js
  2. 导航/main.js

用户启动应用程序后,用户会看到 navigation/index.js 文件中的屏幕。

用户注册或登录后,用户会看到 navigation/main.js 文件中的屏幕

除了在应用程序中登录和注销后在导航器之间导航之外,我已经实现了应用程序中的所有其他内容

我最初将所有屏幕放在同一个导航器文件中,但连续按后退按钮后我开始遇到问题

看下面的代码

:::::::::编辑::::::::::: 不再使用 Navigation/main.js 现在仅使用 Navigation/index.js 并实现 @Tolga Berk Ordanuç 的建议 但仍然需要更多帮助,因为 它部分起作用 现在 单击“登录”登录后出现错误

"错误任何导航器均未处理有效负载 {"name":"BottomTabNavigator"} 的操作“NAVIGATE”。

您有一个名为“BottomTabNavigator”的屏幕吗?”

当我通过多次回击完全关闭应用程序时, 我已登录 但现在第二个错误,当我单击注销时 我收到以下错误

错误任何导航器均未处理有效负载 {"name":"Walkthrough"} 的操作“NAVIGATE”。

您有一个名为“演练”的屏幕吗?

home.js

import React, {useState} from 'react';
import {View} from 'react-native';
import {useTheme} from '@config';
import {Header, Icon, Button} from '@components';
import {useDispatch} from 'react-redux';

export default function Home({navigation, route}) {
  const {colors} = useTheme();
     const dispatch = useDispatch();

  const [loading, setLoading] = useState(false);


  const logout = () => {
    setLoading(true);
    dispatch(setIsLoggedIn(false));

    navigation.navigate('SignIn');

    setLoading(false);
  };

  return (
    <View style={{flex: 1}}>
      <Header
        title="sign in"
        renderLeft={() => {
          return (
            <Icon
              name="times"
              size={20}
              color={colors.primary}
              enableRTL={true}
            />
          );
        }}
        onPressLeft={() => {
          navigation.goBack();
        }}
      />
      <View>
        <Button style={{marginTop: 20}} full loading={loading} onPress={logout}>
          Log Out
        </Button>
      </View>
    </View>
  );
}
  • 导航/main.js

    import React from 'react';
    import {createStackNavigator} from '@react-navigation/stack';
    import {useTheme} from '@config';
    import {useSelector} from 'react-redux';
    import {designSelect} from '@selectors';
    
    import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
    import {BaseColor, useFont} from '@config';
    import {Icon} from '@components';
    
    /* Main Stack Navigator */
    /* Modal Screen only affect iOS */
    
    import Savings from 'Savings';
    import Loans from 'Loans';
    
    import Home from 'Home';
    
    import Profile from 'Profile';
    
    /* Stack Screen */
    import Setting from 'Setting';
    import Feedback from 'Feedback';
    import ChangePassword from 'ChangePassword';
    import ProfileEdit from 'ProfileEdit';
    import ContactUs from 'ContactUs';
    import AboutUs from 'AboutUs';
    import Support from 'Support';
    
    const MainStack = createStackNavigator();
    
    export default function Main() {
      return (
        <MainStack.Navigator
          screenOptions={{
            headerShown: false,
          }}
          initialRouteName="BottomTabNavigator">
          <MainStack.Screen
            name="BottomTabNavigator"
            component={BottomTabNavigator}
          />
          <MainStack.Screen name="Support" component={Support} />
          <MainStack.Screen name="SavingsTemp" component={Savings} />
          <MainStack.Screen
            name="BottomTabNavigator"
            component={BottomTabNavigator}
          />
    
          <MainStack.Screen name="Setting" component={Setting} />
          <MainStack.Screen name="Feedback" component={Feedback} />
          <MainStack.Screen name="ChangePassword" component={ChangePassword} />
          <MainStack.Screen name="ProfileEdit" component={ProfileEdit} />
          <MainStack.Screen name="ContactUs" component={ContactUs} />
          <MainStack.Screen name="AboutUs" component={AboutUs} />
        </MainStack.Navigator>
      );
    }
    
    function BottomTabNavigator() {
      const {colors} = useTheme();
      const font = useFont();
      const BottomTab = createBottomTabNavigator();
      const design = useSelector(designSelect);
    
      /**
       * Main follow return  Home Screen design you are selected
       * @param {*} design  ['basic', 'real_estate','event', 'food']
       * @returns
       */
      const exportHome = () => {
        return Home;
      };
    
      return (
        <BottomTab.Navigator
          initialRouteName="Home"
          screenOptions={{
            headerShown: false,
          }}
          tabBarOptions={{
            showIcon: true,
            showLabel: true,
            activeTintColor: colors.primary,
            inactiveTintColor: BaseColor.grayColor,
            style: {borderTopWidth: 1},
            labelStyle: {
              fontSize: 12,
              fontFamily: font,
              paddingBottom: 4,
            },
          }}>
          <BottomTab.Screen
            name="Home"
            component={exportHome(design)}
            options={{
              title: 'home',
              tabBarIcon: ({color}) => {
                return <Icon color={color} name="home" size={20} solid />;
              },
            }}
          />
    
          <BottomTab.Screen
            name="Savings"
            component={Savings}
            options={{
              title: 'Savings',
              tabBarIcon: ({color}) => {
                return <Icon color={color} name="bookmark" size={20} solid />;
              },
            }}
          />
          <BottomTab.Screen
            name="Loans"
            component={Loans}
            options={{
              title: 'Loans',
              tabBarIcon: ({color}) => {
                return <Icon color={color} name="clipboard-list" size={20} solid />;
              },
            }}
          />
          <BottomTab.Screen
            name="Profile"
            component={Profile}
            options={{
              title: 'Profile',
              tabBarIcon: ({color}) => {
                return <Icon solid color={color} name="user-circle" size={20} />;
              },
            }}
          />
        </BottomTab.Navigator>
      );
    }
    
  • 导航/index.js

       import React, {useEffect, useState} from 'react';
    import {StatusBar, Platform} from 'react-native';
    import {NavigationContainer} from '@react-navigation/native';
    import {createStackNavigator} from '@react-navigation/stack';
    import {DarkModeProvider, useDarkMode} from 'react-native-dark-mode';
    import {useTheme, BaseSetting} from '@config';
    import i18n from 'i18next';
    import {initReactI18next} from 'react-i18next';
    import {useSelector} from 'react-redux';
    import {languageSelect, designSelect} from '@selectors';
    
    import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
    import {BaseColor, useFont} from '@config';
    import {useTranslation} from 'react-i18next';
    import {Icon} from '@components';
    
    /* Main Stack Navigator */
    /* Modal Screen only affect iOS */
    import Loading from 'Loading';
    
    import SignIn from 'SignIn';
    import SignUp from 'SignUp';
    import ResetPassword from 'ResetPassword';
    
    import Walkthrough from 'Walkthrough';
    
    import Home from 'Home';
    
    import Profile from 'Profile';
    
    import Feedback from 'Feedback';
    import ChangePassword from 'ChangePassword';
    import ProfileEdit from 'ProfileEdit';
    import ContactUs from 'ContactUs';
    import AboutUs from 'AboutUs';
    import Tab2 from 'Tab2';
    import Tab3 from 'Tab3';
    import BottomTabNavigator from './BottomTabNavigator';
    import {store} from '../store';
    
    const RootStack = createStackNavigator();
    
    export default function Navigator() {
      const language = useSelector(languageSelect);
    
      const {theme, colors} = useTheme();
      const isDarkMode = useDarkMode();
      const [isLoggedInValue, setIsLoggedInValue] = useState(false);
    
      useEffect(() => {
        i18n.use(initReactI18next).init({
          resources: BaseSetting.resourcesLanguage,
          lng: language ?? BaseSetting.defaultLanguage,
          fallbackLng: BaseSetting.defaultLanguage,
        });
        if (Platform.OS === 'android') {
          StatusBar.setBackgroundColor(colors.primary, true);
        }
        StatusBar.setBarStyle(isDarkMode ? 'light-content' : 'dark-content', true);
        console.log('<<<<< IS LOGGED IN STATE >>>>>>');
        console.log(isLoggedInValue);
        console.log('<<<<< IS LOGGED IN STATE >>>>>>');
        setIsLoggedInValue(store.getState().isloggedin.isLoggedIn);
      }, [colors.primary, isDarkMode, language, isLoggedInValue]);
    
      return (
        <DarkModeProvider>
          <NavigationContainer theme={theme}>
            <RootStack.Navigator
              mode="modal"
              screenOptions={{
                headerShown: false,
              }}>
              {!isLoggedInValue ? (
                <>
                  <RootStack.Screen
                    name="Loading"
                    component={Loading}
                    options={{gestureEnabled: false}}
                  />
                  <RootStack.Screen name="Walkthrough" component={Walkthrough} />
                  <RootStack.Screen name="SignIn" component={SignIn} />
                  <RootStack.Screen name="SignUp" component={SignUp} />
                  <RootStack.Screen
                    name="ResetPassword"
                    component={ResetPassword}
                  />
                </>
              ) : (
                <>
                  <RootStack.Screen
                    name="BottomTabNavigator"
                    component={BottomTabNavigator}
                  />
    
                  <RootStack.Screen name="Feedback" component={Feedback} />
                  <RootStack.Screen
                    name="ChangePassword"
                    component={ChangePassword}
                  />
                  <RootStack.Screen name="ProfileEdit" component={ProfileEdit} />
                  <RootStack.Screen name="ContactUs" component={ContactUs} />
                  <RootStack.Screen name="AboutUs" component={AboutUs} />
                </>
              )}
            </RootStack.Navigator>
          </NavigationContainer>
        </DarkModeProvider>
      );
    }
    
  • 登录.js

    import React, {useState} from 'react';
    import {
      View,
      TouchableOpacity,
      KeyboardAvoidingView,
      Platform,
      Alert,
    } from 'react-native';
    import {useDispatch} from 'react-redux';
    import {BaseStyle, useTheme} from '@config';
    import {Header, SafeAreaView, Icon, Text, Button, TextInput} from '@components';
    import styles from './styles';
    
    export default function SignIn({navigation, route}) {
      const {colors} = useTheme();
    
      const [loading, setLoading] = useState(false);
      const [id, setId] = useState('');
      const [password, setPassword] = useState('');
      const dispatch = useDispatch();
    
      /**
       * call when action onLogin
       */
      const onLogin = () => {
        setLoading(true);
     dispatch(setIsLoggedIn(true));
        navigation.navigate('Home');
    
        setLoading(false);
      };
    
      const offsetKeyboard = Platform.select({
        ios: 0,
        android: 20,
      });
    
      return (
        <View style={{flex: 1}}>
          <Header
            title="sign in"
            renderLeft={() => {
              return (
                <Icon
                  name="times"
                  size={20}
                  color={colors.primary}
                  enableRTL={true}
                />
              );
            }}
            onPressLeft={() => {
              navigation.goBack();
            }}
          />
          <SafeAreaView style={BaseStyle.safeAreaView} edges={['right', 'left']}>
            <KeyboardAvoidingView
              behavior={Platform.OS === 'android' ? 'height' : 'padding'}
              keyboardVerticalOffset={offsetKeyboard}
              style={{flex: 1}}>
              <View style={styles.contain}>
                <TextInput onChangeText={setId} placeholder="username" value={id} />
                <TextInput
                  style={{marginTop: 10}}
                  onChangeText={setPassword}
                  placeholder="Password"
                  secureTextEntry={true}
                  value={password}
                />
                <Button
                  style={{marginTop: 20}}
                  full
                  loading={loading}
                  onPress={onLogin}>
                  'sign_in'
                </Button>
                <TouchableOpacity
                  onPress={() => navigation.navigate('ResetPassword')}>
                  <Text body1 grayColor style={{marginTop: 25}}>
                    'forgot_your_password'
                  </Text>
                </TouchableOpacity>
              </View>
            </KeyboardAvoidingView>
          </SafeAreaView>
        </View>
      );
    }
    

    5

    导航/BottomTabNavigator.js

       export default function BottomTabNavigator() {
    
          const {colors} = useTheme();
          const font = useFont();
          const design = useSelector(designSelect);
          const BottomTab = createBottomTabNavigator();
        
          const exportHome = () => {
            return Home;
          };
        
          return (
            <BottomTab.Navigator
              initialRouteName="Home"
              screenOptions={{
                headerShown: false,
              }}
              tabBarOptions={{
                showIcon: true,
                showLabel: true,
                activeTintColor: colors.primary,
                inactiveTintColor: BaseColor.grayColor,
                style: {borderTopWidth: 1},
                labelStyle: {
                  fontSize: 12,
                  fontFamily: font,
                  paddingBottom: 4,
                },
              }}>
              <BottomTab.Screen
                name="Home"
                component={exportHome(design)}
                options={{
                  title: 'Home',
                  tabBarIcon: ({color}) => {
                    return <Icon color={color} name="home" size={20} solid />;
                  },
                }}
              />
        
              <BottomTab.Screen
                name="Savings"
                component={Tab2}
                options={{
                  title: 'Savings',
                  tabBarIcon: ({color}) => {
                    return <Icon color={color} name="bookmark" size={20} solid />;
                  },
                }}
              />
              <BottomTab.Screen
                name="Loans"
                component={Tab3}
                options={{
                  title: 'Loans',
                  tabBarIcon: ({color}) => {
                    return <Icon color={color} name="clipboard-list" size={20} solid />;
                  },
                }}
              />
              <BottomTab.Screen
                name="Profile"
                component={Profile}
                options={{
                  title: 'Profile',
                  tabBarIcon: ({color}) => {
                    return <Icon solid color={color} name="user-circle" size={20} />;
                  },
                }}
              />
            </BottomTab.Navigator>
          );
        }
    

    最佳答案

    我在代码中看不到第二个选项卡导航器,但我看到您在组件内创建了导航器,在我看来,这不是您应该做的。您应该单独创建导航器,而不是在另一个组件内。在 react-navigation 的文档中,他们以这种方式显示,所以他们应该知道他们在做什么,我猜:D

    登录和主应用程序屏幕过去由开关导航器管理,但在 react-navigation 5 中,它们转储了开关导航器,而是在导航器组件中支持三元运算符,如下所示

    const RootStack = createStackNavigator<RootStackParamList>();
    export const RootNavigator = () => {
        const isLoggedIn = useReduxSelector(({ authState }) => authState.isLoggedIn);
        return (
            <RootStack.Navigator screenOptions={{ headerShown: false }}>
                {!isLoggedIn ? (
                    <RootStack.Screen
                        name="AuthNavigator"
                        options={{ headerShown: false }}
                        component={AuthNavigator}
                    />
                ) : (
                    <>
                        <RootStack.Screen name="TabNavigator" component={TabNavigator} />
                        <RootStack.Screen
                            name="DetailsNavigator"
                            component={DetailsNavigator}
                        />
                        <RootStack.Screen
                            name="UserStackNavigator"
                            component={UserStackNavigator}
                        />
                        <RootStack.Screen name="Announcements" component={Announcements} />
                        <RootStack.Screen name="Read" component={Read} />
                        <RootStack.Screen
                            name="Search"
                            options={{
                                ...TransitionPresets.FadeFromBottomAndroid,
                                gestureEnabled: false,
                            }}
                            component={Search}
                        />
                    </>
                )}
            </RootStack.Navigator>
        );
    };
    

    登录并为您的 redux 分派(dispatch)适当的操作以更改 isLoggedIn 状态后,导航器会自动删除登录页面并回退到其下方的内容。此时,用户无法转到登录或注册屏幕,即使他们想返回多少次也是如此,因为我们将这些屏幕从导航树中删除了。

    如果您想返回登录屏幕,您只需注销用户,导航树就会再次包含这些屏幕,您可以使用屏幕的相应按键通过 navigation.navigate 功能导航到它们。

    如果您好奇我的选项卡导航器是什么样子,它就像这样

    const Tab = createBottomTabNavigator<TabParamList>();
    
    //
    
    const tabNavigatorScreenOptions: (props: {
        route: RouteProp<TabParamList, keyof TabParamList>;
        navigation: unknown;
    }) => BottomTabNavigationOptions = ({ route }) => ({
        tabBarIcon: (params) => <TabBarIcon {...params} route={route} />,
        tabBarButton: (props) => (
            <Pressable
                {...props}
                style={[props.style, { marginTop: Layout.dimensions.xs_h }]}
            />
        ),
        // tabBarLabel: (props) => <TabBarLabel {...props} route={route} />,
    });
    
    export const TabNavigator = () => {
        const debug = useReduxSelector(({ info }) => info.debug);
        // Logger.debug = debug;
        return (
            <Tab.Navigator
                tabBarOptions={{ adaptive: true, showLabel: false }}
                screenOptions={tabNavigatorScreenOptions}
            >
                <Tab.Screen name="Discover" component={Discover} />
                <Tab.Screen name="Library" component={LibraryNavigator} />
                <Tab.Screen name="Settings" component={SettingsNavigator} />
                {debug && <Tab.Screen name="TestNavigator" component={TestNavigator} />}
            </Tab.Navigator>
        );
    };
    

    代码是 typescript ,但这不应该是逻辑问题。

    如果您还有任何疑问,我很乐意为您提供帮助!

    祝我的 React Native 开发人员编码愉快!

    关于javascript - 如何在 React Native 中登录和注销后在 2 个不同的导航器之间导航,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68096086/

    相关文章:

    javascript - 如何将纯 JavaScript 重写为 React 组件(foreach)

    reactjs - 将客户端和服务器部署到同一个虚拟机

    对象数组和 indexOf 的 Javascript 奇怪之处

    javascript - jQuery:第一个 child (没有 id 或类)

    javascript - 错误 : $digest already in progress when using two Http request calls in same angular Js function

    javascript - 如何在我的 react slider 中设置显示柔性?

    javascript - React-Native 应用程序中来自 Babel 的未知选项错误

    javascript - 在 React Native 中设置背景颜色动画

    react-native - react 本地 map 聚类

    javascript - 无法对 URL 进行网页截图