因此,我目前正在使用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;
到底是什么问题?
答案 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派遣操作。那是因为我们不需要导航到它们,调度是这里的唯一选择,如果我们尝试从一个堆栈导航到另一个堆栈,则会显示一个红色屏幕。