7

我正在将 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>
  );
}
4

4 回答 4

10

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

于 2020-06-18T12:39:30.047 回答
4

在早期版本的 React Navigation 中,有两种方法可以处理这个问题:

  1. 保留多个导航器并在登录时使用切换导航器将活动导航器切换到不同的导航器(推荐)
  2. 登录时将导航器的状态重置为所需的屏幕

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

于 2020-02-18T10:57:55.647 回答
3

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);
于 2020-02-18T14:59:40.213 回答
3

我遵循了官方文档(https://reactnavigation.org/docs/auth-flow/),它终于奏效了。

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

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

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 变量 <user.token> 中管理令牌的状态。因此,在登录屏幕中,我们不需要使用任何导航,例如 '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));
于 2020-08-10T09:32:58.560 回答