React Navigation 5 如何映射抽屉堆栈屏幕?

React Navigation 5 How to Map Drawer Stack Screens?

我正在尝试做一个动态抽屉,我的 StackItens(路由)设置如下:

import React from 'react';
import Home from '../screens/home/Index';
import ATR from '../screens/atr/Index';

const stackNavigItems = [
  {
    group: 'Home',
    name: 'Home',
    component: Home,
    icon: 'home',
    iconType: 'FontAwesome',
    label: 'Principal',
    hideMenu: false,
    screenComponent: props => {
      return <Home {...props} />;
    },
  },
  {
    group: 'Home',
    name: 'ATR',
    component: ATR,
    icon: 'book',
    iconType: 'Ionicons',
    label: 'ATR',
    hideMenu: false,
    screenComponent: props => {
      return <ATR {...props} />;
    },
  },
];

export {stackNavigItems};

在我的抽屉内容中,我映射了这些项目并且工作正常。 但是当我使用此代码在导航器中映射相同的项目时:

<PaperProvider theme={theme}>
  <AuthContext.Provider value={authContext}>
    <NavigationContainer theme={theme}>
      <Drawer.Navigator drawerContent={props => <DrawerContent {...props} />}>
    {stackNavigItems.map(r => {
      return (
        <Drawer.Screen
          key={r.name}
          name={r.name}
          component={({navigation}) => (
            <Stack.Navigator
              initialRouteName="Home"
              headerMode="screen"
              screenOptions={screenOptions}>
              <Stack.Screen
                name={r.name}
                component={props => <r.screenComponent {...props} />}
                options={{
                  title: r.label,
                  headerLeft: () => (
                    <Icon.Button
                      name="ios-menu"
                      size={IconStyles.size}
                      backgroundColor={AppStyles.color.main}
                      onPress={() => {
                        navigation.openDrawer();
                      }}
                    />
                  ),
                }}
              />
            </Stack.Navigator>
          )}
        />
      );
    })}
  </Drawer.Navigator>
    </NavigationContainer>
  </AuthContext.Provider>
</PaperProvider>

该应用程序总是向我显示此警告并且 header 大小加倍:

我尝试了很多方法在组件之前传递一个函数“()”,但没有任何效果。如果我禁用警告,该应用程序会在不显示警告的情况下运行,但有时 header 在使用图片时会加倍大小。

您可以避免使用内联函数,方法是创建一个额外的组件并正常传递该组件,然后通过 initialParams 将导航项的 id 传递给额外的组件:

const StackNavigator = ({route}) => {
  const navigationItem = stackNavigItems[route.params?.navigationItemId];
  return (
    <Stack.Navigator initialRouteName="Home" headerMode="screen">
      <Stack.Screen
        name={navigationItem.name}
        component={navigationItem.screenComponent}
        options={{
          title: navigationItem.label,
          headerLeft: () => null,
        }}
      />
    </Stack.Navigator>
  );
};

function App() {
  return (
    <NavigationContainer>
      <Drawer.Navigator drawerContent={(props) => null}>
        {stackNavigItems.map((r) => {
          return (
            <Drawer.Screen
              key={r.name}
              name={r.name}
              component={StackNavigator}
              initialParams={{navigationItemId: r.id}}
            />
          );
        })}
      </Drawer.Navigator>
    </NavigationContainer>
  );
}

因此,对于这种方法,您确实需要向 stackNavigItems 中的对象添加一个 id 属性:

const stackNavigItems = [
  {
    id: 0,
    group: 'Home',
    name: 'Home',
    component: Home,
    icon: 'home',
    iconType: 'FontAwesome',
    label: 'Principal',
    hideMenu: false,
    screenComponent: (props) => {
      return <Home {...props} />;
    },
  },
  {
    id: 1,
    group: 'Home',
    name: 'ATR',
    component: ATR,
    icon: 'book',
    iconType: 'Ionicons',
    label: 'ATR',
    hideMenu: false,
    screenComponent: (props) => {
      return <ATR {...props} />;
    },
  },
];

为了使这个示例更具可读性,我省略了一些不相关的代码。

component={r.ScreenComponent}.

在我的例子中,我使用 Stack.Screen,它工作正常。

const stackNavigItems = [
  {
    id: 0,
    group: 'Home',
    name: 'Home',
    component: Home,
    icon: 'home',
    iconType: 'FontAwesome',
    label: 'Principal',
    hideMenu: false,
    screenComponent: (props) => {
      return <Home {...props} />;
    },
  },
  {
    id: 1,
    group: 'Home',
    name: 'ATR',
    component: ATR,
    icon: 'book',
    iconType: 'Ionicons',
    label: 'ATR',
    hideMenu: false,
    screenComponent: (props) => {
      return <ATR {...props} />;
    },
  },
];

...

export default function App() {
  return (
    <PaperProvider>
      <NavigationContainer>
        <Stack.Navigator initialRouteName="Home">
          {stackNavigItems.map((item, index) => {
            return (
              <Stack.Screen key={index} name={item.name} component={item.ScreenComponent} options={{title:item.title}}/>
            )
          })}
        </Stack.Navigator>
      </NavigationContainer>
    </PaperProvider>
  );
}