简体   繁体   English

反应本机抽屉导航器未打开

[英]React native drawer navigator not opening

I'm building a react native app and using react navigation v6 library.我正在构建一个反应原生应用程序并使用反应导航 v6 库。 I've built a react navigator that works fine for the most part, but I'm facing this bug when navigating to a certain page.我已经构建了一个反应导航器,它在大多数情况下都可以正常工作,但是在导航到某个页面时我遇到了这个错误。

I have a stack navigator:我有一个堆栈导航器:

   <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='CocktailDetailScreen' component={CocktailDetailScreen} options={{ header: () => <Header/> }} />

        <Stack.Screen name='HomeScreen' component={DrawerNavigator} options={{ header: () => <Header/> }} />
      </Stack.Navigator>
    </NavigationContainer>

And the drawer navigator:和抽屉导航器:

    <Drawer.Navigator screenOptions={{
        drawerStyle: {
          backgroundColor: 'white',
          zIndex: 100
        },
        drawerPosition: 'right'
      }}>
        <Drawer.Screen name='Search cocktails' component={HomeScreen} options={{headerShown: false}} />
        <Drawer.Screen name='Profile' component={ProfileScreen} options={{headerShown: false}} />
        <Drawer.Screen name='Publish a recipe' component={PublishRecipeScreen} options={{headerShown: false}} />

        <Drawer.Screen name='Favorites' component={FavoritesScreen} options={{headerShown: false}} />
        <Drawer.Screen name='Published recipes' component={PublishedRecipesScreen} options={{headerShown: false}} />
        <Drawer.Screen name='Log out' component={LandingScreen} options={{headerShown: false}} />
    </Drawer.Navigator>

The problem occurs when navigating to CocktailDetailScreen, the thing is the drawer just won't open.导航到 CocktailDetailScreen 时会出现问题,问题是抽屉无法打开。 The drawer is opened from the header component (which is shared by CocktailDetailScreen, homeScreen and all the screens within the drawer) and to open it I'm using navigation.dispatch(DrawerActions.toggleDrawer()) .抽屉从 header 组件(由 CocktailDetailScreen、homeScreen 和抽屉内的所有屏幕共享)打开,我使用navigation.dispatch(DrawerActions.toggleDrawer())打开它。 This works fine on every screen except of this one.这在除此之外的每个屏幕上都可以正常工作。

I've figured that If I remove CocktailDetailScreen from the stack navigator and add it to the drawer navigator, then the drawer opens normally.我想如果我从堆栈导航器中删除 CocktailDetailScreen 并将其添加到抽屉导航器中,那么抽屉会正常打开。 But I don't want this, since this page should only be accessed through other screens, not directly from the "menu"/navigator.但我不希望这样,因为这个页面只能通过其他屏幕访问,而不是直接从“菜单”/导航器访问。

I'm sure this is possible, but I don't get what I'm doing wrong.我确信这是可能的,但我不明白我做错了什么。 Maybe I'm not nesting the navigators correctly or the screen shouldn't be in the navigator at all?也许我没有正确嵌套导航器,或者屏幕根本不应该在导航器中?

Full code is here: https://github.com/coccagerman/mixr完整代码在这里: https://github.com/coccagerman/mixr

Drawer Navigator is nested inside Stack Navigator, Screens below can access drawer specific actions ( open, close or toggle)抽屉导航器嵌套在堆栈导航器内,下面的屏幕可以访问抽屉特定的操作(打开、关闭或切换)

  • Search cocktails搜索鸡尾酒
  • Profile轮廓
  • Publish a recipe发布食谱
  • Favorites收藏夹
  • Published recipes已发表的食谱
  • Log out登出

due to they are children to a Drawer navigator.因为他们是抽屉导航器的孩子。

To make Drawer actions accessible to all screens, the Drawer must be a parent to all navigators.要使所有屏幕都可以访问 Drawer 操作,Drawer 必须是所有导航器的父级。

Let's refactor our code as below.让我们重构我们的代码,如下所示。


const PublicStack = (
  <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="CocktailDetailScreen"
      component={CocktailDetailScreen}
      options={{ header: () => <Header /> }}
    />

    <Stack.Screen
      name="HomeScreen"
      component={DrawerNavigator}
      options={{ header: () => <Header /> }}
    />
  </Stack.Navigator>
);

const ProtectedStack = () => (
  <Stack.Navigator>
    <Stack.Screen
      name="Search cocktails"
      component={HomeScreen}
      options={{ headerShown: false }}
    />
    <Stack.Screen
      name="Profile"
      component={ProfileScreen}
      options={{ headerShown: false }}
    />
    <Stack.Screen
      name="Publish a recipe"
      component={PublishRecipeScreen}
      options={{ headerShown: false }}
    />

    <Stack.Screen
      name="Favorites"
      component={FavoritesScreen}
      options={{ headerShown: false }}
    />
    <Stack.Screen
      name="Published recipes"
      component={PublishedRecipesScreen}
      options={{ headerShown: false }}
    />
    <Stack.Screen
      name="Log out"
      component={LandingScreen}
      options={{ headerShown: false }}
    />
  </Stack.Navigator>
);

const MainStack = () => {
  // Mocked logic for authentication, Implement actually logic
  const isLoggedIn = true;

  return (
    <NavigationContainer>
      <Drawer.Navigator
        screenOptions={{
          drawerStyle: {
            backgroundColor: "white",
            zIndex: 100,
          },
          drawerPosition: "right",
        }}
      >
        {isLoggedIn ? (
          <Stack.Screen
            name="ProtectedStack"
            component={ProtectedStack}
            options={{ header: () => <Header /> }}
          />
        ) : (
          <Stack.Screen
            name="PublicStack"
            component={PublicStack}
            options={{ header: () => <Header /> }}
          />
        )}

        {/* This screen can be accessible even if when user is not authenticated */}

        <Drawer.Screen
          name="CocktailDetailScreen"
          component={CocktailDetailScreen}
          options={{ header: () => <Header /> }}
        />
      </Drawer.Navigator>
    </NavigationContainer>
  );
};


This is reference, refactor and structure navigation your requirements.这是您的要求的参考、重构和结构导航。

Explore more at https://reactnavigation.org/docs/nesting-navigators/#navigator-specific-methods-are-available-in-the-navigators-nested-insidehttps://reactnavigation.org/docs/nesting-navigators/#navigator-specific-methods-are-available-in-the-navigators-nested-inside探索更多信息

My implementation was the following:我的实现如下:

import { NavigationContainer } from '@react-navigation/native'
import { createNativeStackNavigator } from '@react-navigation/native-stack'
import { createDrawerNavigator } from '@react-navigation/drawer'

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 FavoritesScreen from '../screens/FavoritesScreen'
import PublishedRecipesScreen from '../screens/PublishedRecipesScreen'

import Header from '../components/Header'

import { RootStackParamList } from '../types'

export default function Navigation() {

  const Stack = createNativeStackNavigator<RootStackParamList>()
  const Drawer = createDrawerNavigator()

  const isLoggedIn = false

  const loginStack = () => (
    <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.Navigator>
  )

  return (
    <NavigationContainer>
      <Drawer.Navigator screenOptions={{
        drawerStyle: { backgroundColor: 'white' },
        drawerPosition: 'right'
      }}>

        {!isLoggedIn ? (
          <Stack.Screen
            name="PublicStack"
            component={loginStack}
            options={{headerShown: false}}
          /> )
        :
        (<>
          <Drawer.Screen name='Search cocktails' component={HomeScreen} options={{ header: () => <Header/> }} />
          <Drawer.Screen name='Profile' component={ProfileScreen} options={{ header: () => <Header/> }} />
          <Drawer.Screen name='Publish a recipe' component={PublishRecipeScreen} options={{ header: () => <Header/> }} />
          <Drawer.Screen name='Favorites' component={FavoritesScreen} options={{ header: () => <Header/> }} />
          <Drawer.Screen name='Published recipes' component={PublishedRecipesScreen} options={{ header: () => <Header/> }} />
          <Drawer.Screen name='Log out' component={LandingScreen} options={{ header: () => <Header/> }} />

          <Drawer.Screen name='CocktailDetailScreen' component={CocktailDetailScreen} options={{
            header: () => <Header/>,
            drawerLabel: () => null,
            title: undefined
          }} />
        </>
        )}

      </Drawer.Navigator>
    </NavigationContainer>
  )
}

I made the drawer navigator the main navigator, and made a different stack navigator just for the landing, register and login pages.我将抽屉导航器设为主导航器,并为登陆、注册和登录页面制作了一个不同的堆栈导航器。

Within the drawer, I have this separate stack navigator as a child screen and passing it the stack navigator as the component.在抽屉中,我将这个单独的堆栈导航器作为子屏幕并将堆栈导航器作为组件传递给它。

The drawer screens remain the same as I had them before, except now CocktailDetailScreen is a child of drawer navigator too and thanks to that I can now action on it.抽屉屏幕和我之前的一样,除了现在 CocktailDetailScreen 也是抽屉导航器的孩子,多亏了它,我现在可以对其进行操作。 Since I don't want that screen to be accessible through the navigator menu, I just don't render it there using drawerLabel: () => null, title: undefined由于我不希望通过导航菜单访问该屏幕,我只是不使用drawerLabel: () => null, title: undefined

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM