createSwitchNavigator 在 react-navigation 5.x 中的位置,用于从 react-navigation 4 迁移到 5.x

Where is placed createSwitchNavigator in react-navigation 5.x for migrating from react-navigation 4 to 5.x

我正在将 React Native 应用程序从 react-navigation 4 迁移到 5.x,但我找不到哪个包包含 createSwitchNavigation。具体来说,我对授权令牌检查部分有疑问。

使用 react-navigation 4 我有:

const switchNavigator = createSwitchNavigator({
  ResolveAuth: ResolveAuthScreen,
  signinFlow: createStackNavigator({
    Signup: SignupScreen,
    Signin: SigninScreen,
  }),
  appFlow: createBottomTabNavigator({
    TrackCreate: TrackCreateScreen,
    trackListFlow: createStackNavigator({
      TrackList: TrackListScreen,
      TrackDetail: TrackDetailScreen
    }),
    Account: AccountScreen,
  })
}, {
  initialRouteName: 'ResolveAuth'
});

然后我有一个包含 ResolveAuthScreen 组件的文件。

import React, { useEffect } from 'react';
import { connect } from 'react-redux';

const ResolveAuthScreen = (props) => {
  useEffect(() => {
    if (!props.token) {
      props.navigation.navigate('loginFlow');
    } else {
      props.navigation.navigate('TrackList');
    }
  }, []);

  return null;
};

const mapStateToProps = (state) => {
  return {
    token: state.auth.token,
  };
};

export default connect(mapStateToProps, null)(ResolveAuthScreen);

其余的组件对于这个疑问并不重要。我想知道如何复制相同的 Switch 导航流程。 我想知道如何创建这样的东西:

const Switch = createSwitchNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Switch.Navigator>
        <Switch.Screen name="ResolveAuth" component={ResolveAuthScreen} />
        <Switch.Screen name="signinFlow" component={SignInFlowScreens} />
        <Switch.Screen name="appFlow" component={AppFlowScreens} />
      </Switch.Navigator>
    </NavigationContainer>
  );
}

In earlier versions of React Navigation, there were 2 ways to handle this:

  1. Keep multiple navigators and use switch navigator to switch the active navigator to a different one upon login (recommended)
  2. Reset the state of the navigator to the desired screens upon login

但是对于 v5,您需要使用上下文。看看here看详细的例子!

v5 上没有切换导航器。你可以试试下面的代码

function App({ token }) {
  const [isLoggedIn, setLoggedIn] = useState(false);

  useEffect(() => {
    setLoggedIn(!!token);
  }, [token]);

  return (
    <NavigationContainer>
      {isLoggedIn ? <AppFlowScreens /> : <SignInFlowScreens /> }
    </NavigationContainer>
  );
}

const mapStateToProps = (state) => {
  return {
    token: state.auth.token,
  };
};

export default connect(mapStateToProps, null)(App);

为了使迁移更容易,您仍然可以使用@react-navigation/compat

中的createSwitchNavigator

按照官方文档(https://reactnavigation.org/docs/auth-flow/)进行操作,终于成功了。

关键部分是用于检查用户是否登录的变量必须是全局变量(可从任何屏幕访问)。就我而言,我使用了 Redux。

这是 App 导航的主要代码,我首先检查是否有来自 AsyncStorage 的令牌,然后转到 tabBar 屏幕(Home、Profile...)或登录屏幕:

import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { setToken } from '../store/actions/user';
import AsyncStorage from '@react-native-community/async-storage';

...

const appNavigator = () => {

  const dispatch = useDispatch();
  const user = useSelector(state => state.user);

  useEffect(() => {
    const getToken = async () => dispatch(setToken(await AsyncStorage.getItem('token')));
    getToken();
  }, [])

  return (
    <NavigationContainer>
        {(user.token == null)
            ? <LoginStackScreen />
            : <AppTabScreens />
        }
    </NavigationContainer>
  ) 
};

在这种情况下,我在 redux 变量 中管理令牌的状态。因此,在登录屏幕中,我们不需要使用任何导航,例如“navigation.navigate('Home')”。我们只需要在用户登录并生成新令牌后更新 redux 变量:

      //props.navigation.navigate('Home');
      dispatch(setToken(newToken));

这将自动转到主屏幕,无需任何其他导航。

对于注销,我们只需将此 redux 变量设置为 null(同样,无需使用 navigation.navigate):

     await AsyncStorage.clear();
     //props.navigation.navigate('Auth');
     dispatch(setToken(null));