反应导航v4到v5问题

时间:2020-03-13 12:05:00

标签: react-native react-navigation react-navigation-v5

因此,我目前正在使用SwitchNavigator导航v4。我想迁移到v5,但无法像Switch那样正常工作。我有3个堆栈,AuthStack(堆栈导航器),TabScreens(它是底部导航器),Terms(仅一个屏幕),而我的v4配置是这样的:

  const createRootNavigator = (signedIn = false, terms) => {
  return createAppContainer(
    createSwitchNavigator(
      {
        Auth: { screen: AuthStack, path: 'auth' },
        App: { screen: TabScreens, path: 'app' },
        Terms: { screen: Terms }
      },
      {
        initialRouteName: !signedIn ? !terms ? 'Terms' : 'Auth' : 'App',
        headerMode: 'none',
        defaultNavigationOptions: {
          gestureEnabled: false
        }
      }
    ))
}

因此,第一次出现“条款”屏幕并按“下一步”时,我将自动导航到“身份验证”,如果我按了android后退按钮,则该应用程序将关闭,因为“身份验证”堆栈是主堆栈。但是在v5上不会发生相同的情况。我有一个错误,The action 'NAVIGATE' with payload {"name":"Auth"} was not handled by any navigator. Do you have a screen named 'Auth'?

我的进行中v5配置如下:

const AuthStack = createStackNavigator();
const Auth = () => (
  <AuthStack.Navigator
    initialRouteName={"SignIn"}>
    <AuthStack.Screen
      name={"SignIn"}
      component={SignIn}
      screenOptions={{ gestureEnabled: false }}
      options={{ headerShown: false }}
    />
  </AuthStack.Navigator>
)

const TermsStack = createStackNavigator();
const TermsScreen = () => (
  <TermsStack.Navigator
    initialRouteName={"Terms"}>
    <TermsStack.Screen
      name={"Terms"}
      component={Terms}
      screenOptions={{ gestureEnabled: false }}
      options={{ headerShown: false }}
    />
  </TermsStack.Navigator>
)


const RootScreens = () => {
  const signedIn = mySDK.isAuthorized();
  const terms = myApi.getTerms();

  return (
    <NavigationContainer>
      {!signedIn ?
        <>
          {!terms ?
            <TermsScreen />
            :
            <Auth />
          }
        </>
        :
        // <App />
        <Auth />
      }
    </NavigationContainer>
  )
};

export default RootScreens;

到底是什么问题?

1 个答案:

答案 0 :(得分:1)

因此,我终于设法使其正常运行。下面是演示代码。

import TabScreens from './TabScreens';
        
const AuthStack = createStackNavigator();
const Auth = () => (
<AuthStack.Navigator
        initialRouteName={"LoginMethods"}>
        <AuthStack.Screen
          name={"LoginMethods"}
          component={LoginMethods}
          screenOptions={{ gestureEnabled: false }}
          options={{
            headerShown: false,
            ...TransitionPresets.ModalSlideFromBottomIOS
          }}
        />
    
        <AuthStack.Screen
          name={"Login"}
          component={Login}
          screenOptions={{ gestureEnabled: false }}
          options={{
            headerShown: false,
            ...TransitionPresets.SlideFromRightIOS
          }}
        />
    
        <AuthStack.Screen
          name={"SignUp"}
          component={SignUp}
          screenOptions={{ gestureEnabled: false }}
          options={{
            headerShown: false,
            ...TransitionPresets.SlideFromRightIOS
          }}
        />
    
        <AuthStack.Screen
          name={"ForgotPassword"}
          component={ForgotPassword}
          screenOptions={{ gestureEnabled: false }}
          options={{
            headerShown: false,
            ...TransitionPresets.SlideFromRightIOS
          }}
        />
    
        <AuthStack.Screen
          name={"ChangePassword"}
          component={ChangePassword}
          screenOptions={{ gestureEnabled: false }}
          options={{
            headerShown: false,
            ...TransitionPresets.SlideFromRightIOS
          }}
        />
      </AuthStack.Navigator>
    );


const TermsStack = createStackNavigator();
const TermsScreen = () => (
  <TermsStack.Navigator
    initialRouteName={"Privacy"}>
    <TermsStack.Screen
      name={"Privacy"}
      component={Privacy}
      screenOptions={{ gestureEnabled: false }}
      options={{
        headerShown: false,
        ...TransitionPresets.SlideFromRightIOS
      }}
    />
    <TermsStack.Screen
      name={"Terms"}
      component={Terms}
      screenOptions={{ gestureEnabled: false }}
      options={{
        headerShown: false,
        ...TransitionPresets.SlideFromRightIOS
      }}
    />
  </TermsStack.Navigator>
);


const RootScreens = () => {
  const ref = React.useRef();
  const routeNameRef = React.useRef();

  const signedIn = useSelector(state => state.profile.authorized);
  const showTerms = useSelector(state => state.content.terms);

  //***** Save the initial route name *****/
  React.useEffect(() => {
    routeNameRef.current = signedIn ? 'App' : !showTerms ? 'Terms' : 'Auth';
  }, []);
  //***** Save the initial route name *****/

  const [initialState, setInitialState] = React.useState();

  return (
    <NavigationContainer
      ref={ref}
      initialState={initialState}
      onStateChange={(state) => {
        const prevScreen = routeNameRef.current;
        const currentScreen = getActiveRouteName(state);
        if (prevScreen !== currentScreen) {
          // sendEvent('screen:' + currentScreen, false);
        }
        // Save the current route name for later comparision
        routeNameRef.current = currentScreen;
      }}>
      {
    signedIn ?
        (
            <TabScreens />
        )
        : !showTerms ?
            (
                <TermsScreen />
            )
            :
            (
                <Auth />
            )
}
    </NavigationContainer>
  )
};

正如您在这里看到的那样,我们已经实现了React所谓的动态导航。我们在redux存储中有一些值,当它们更改时,Navigation Container将根据情况动态重新渲染(内联if-else条件)。因此,例如,在应用程序的第一次打开时,我们显示“条款”屏幕(useSelector(state => state.content.terms)为false),当我们按下按钮接受条款时,我们会以true调度该操作。然后,应用程序现在知道showTerms为true,但signIn仍然为false,因此转到登录屏幕。当我们按下登录按钮并完成与服务器的登录过程后,我们将使用true调度signIn变量,并且应用程序将自身导航到其他屏幕(主应用程序的Tabscreens)。

请记住,我没有提到导航到那些堆栈(Terms,Auth)的任何地方,而只是提到了redux派遣操作。那是因为我们不需要导航到它们,调度是这里的唯一选择,如果我们尝试从一个堆栈导航到另一个堆栈,则会显示一个红色屏幕。