【发布时间】:2022-01-31 03:25:44
【问题描述】:
所以我是反应原生和反应导航的新手。
我正在构建一个有 7 个主屏幕的应用:
- HomeScreen、ProfileScreen、CocktailDetailScreen 和 PublishRecipeScreen(我希望能够通过抽屉导航器访问)。
- LandingScreen、LoginScreen 和 RegisterScreen(我不想在抽屉导航器中显示。我只想在用户未登录时显示 LandingScreen,如果用户想登录则显示其中之一或注册)。
我已经能够建立一个工作正常的堆栈导航器,但我不明白如何将它与我想要的抽屉导航器结合起来。我尝试了不同的方法,但出现如下错误:
The action 'OPEN_DRAWER' was not handled by any navigator.
Is your screen inside a Drawer navigator?
或
Uncaught Error: Looks like you have nested a 'NavigationContainer' inside another. Normally you need only one container at the root of the app, so this was probably an error. If this was intentional, pass 'independent={true}' explicitly. Note that this will make the child navigators disconnected from the parent and you won't be able to navigate between them.
到目前为止,这是我的代码。 App.tsx
import { SafeAreaProvider } from 'react-native-safe-area-context'
import useCachedResources from './hooks/useCachedResources'
import Navigation from './navigation'
export default function App() {
const isLoadingComplete = useCachedResources()
if (!isLoadingComplete) {
return null
} else {
return (
<SafeAreaProvider>
<Navigation />
</SafeAreaProvider>
)
}
}
(导航)index.tsx
import { NavigationContainer } from '@react-navigation/native'
import { createNativeStackNavigator } from '@react-navigation/native-stack'
import * as React from 'react'
import LandingScreen from '../screens/LandingScreen'
import LoginScreen from '../screens/LoginScreen'
import RegisterScreen from '../screens/RegisterScreen'
import HomeScreen from '../screens/HomeScreen'
import ProfileScreen from '../screens/ProfileScreen'
import CocktailDetailScreen from '../screens/CocktailDetailScreen'
import PublishRecipeScreen from '../screens/PublishRecipeScreen'
import Header from '../components/Header'
import DrawerNavigator from '../components/DrawerNavigator'
import { RootStackParamList } from '../types'
export default function Navigation() {
const Stack = createNativeStackNavigator<RootStackParamList>()
return (
<NavigationContainer>
<Stack.Navigator >
<Stack.Screen name='LandingScreen' component={LandingScreen} options={{headerShown: false}} />
<Stack.Screen name='LoginScreen' component={LoginScreen} options={{headerShown: false}} />
<Stack.Screen name='RegisterScreen' component={RegisterScreen} options={{headerShown: false}} />
<Stack.Screen name='HomeScreen' component={HomeScreen} options={{ header: () => <Header/> }} />
<Stack.Screen name='ProfileScreen' component={ProfileScreen} options={{ header: () => <Header/> }} />
<Stack.Screen name='CocktailDetailScreen' component={CocktailDetailScreen} options={{ header: () => <Header/> }} />
<Stack.Screen name='PublishRecipeScreen' component={PublishRecipeScreen} options={{ header: () => <Header/> }} />
</Stack.Navigator>
</NavigationContainer>
)
}
header.tsx
import React from 'react'
import { useNavigation } from '@react-navigation/native'
import { useDrawerStatus } from '@react-navigation/drawer'
import { DrawerActions } from '@react-navigation/native'
import { StyleSheet, Text, View } from 'react-native'
import { AntDesign } from '@expo/vector-icons'
const Header = () => {
const navigation = useNavigation()
return (
<View style={styles.container}>
<Text style={styles.title} onPress={() => navigation.navigate('RegisterScreen')}>Mixr</Text>
<View style={styles.iconContainer} >
<AntDesign name='user' style={styles.icon} size={30} color='white' onPress={() => navigation.dispatch(DrawerActions.openDrawer())} />
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: '#E51C27',
alignSelf: 'stretch'
},
title: {
fontSize: 40,
fontWeight: 'bold',
marginTop: 6,
marginBottom: 6,
marginLeft: 10
},
iconContainer: {
backgroundColor: 'black',
borderBottomLeftRadius: 50,
borderBottomRightRadius: 50,
borderTopLeftRadius: 50,
borderTopRightRadius: 50,
marginRight: 10
},
icon: {
padding: 5
}
})
export default Header
DrawerNavigator.tsx
import React from 'react'
import { createDrawerNavigator, useDrawerStatus } from '@react-navigation/drawer'
import { NavigationContainer } from '@react-navigation/native'
import HomeScreen from '../screens/HomeScreen'
import ProfileScreen from '../screens/ProfileScreen'
import CocktailDetailScreen from '../screens/CocktailDetailScreen'
import PublishRecipeScreen from '../screens/PublishRecipeScreen'
const DrawerNavigator = () => {
const Drawer = createDrawerNavigator()
return (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name='HomeScreen' component={HomeScreen} />
<Drawer.Screen name='ProfileScreen' component={ProfileScreen} />
<Drawer.Screen name='CocktailDetailScreen' component={CocktailDetailScreen} />
<Drawer.Screen name='PublishRecipeScreen' component={PublishRecipeScreen} />
</Drawer.Navigator>
</NavigationContainer>
)
}
export default DrawerNavigator
我想在所有这些页面(HomeScreen、ProfileScreen、CocktailDetailScreen 和 PublishRecipeScreen)中显示一个标题,并且可以从该标题打开/关闭抽屉。我不太明白如何将堆栈导航器与抽屉链接。
从更理论的角度来看,我不太了解堆栈导航器、抽屉和其他选项(如选项卡或底部导航器)之间的区别。
我的意思是,除了抽屉导航器显示在抽屉中,底部的导航器显示在底部之外。它们之间有概念上的区别吗?
完整代码可以在这里找到:https://github.com/coccagerman/mixr
【问题讨论】:
标签: react-native expo react-navigation react-navigation-stack react-navigation-drawer