React Navigation 5 Как сопоставить экраны стека ящиков?

#react-native #react-navigation #react-navigation-stack #react-navigation-v5 #react-navigation-drawer

#react-native #реагирующая навигация #реагируйте-навигация-стек #реагирующая навигация-v5 #реагирующая навигация-ящик

Вопрос:

Я пытаюсь создать динамический ящик, мои стеки (маршруты) устанавливаются следующим образом:

 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>
  

Приложение всегда показывает мне это предупреждение, а заголовок удваивает размер:

введите описание изображения здесь

Я перепробовал так много способов передачи функции «()» перед компонентом, и ничего не работает. Если я отключу предупреждение, приложение будет работать без отображения предупреждения, но иногда заголовок удваивает размер при использовании, как на картинке.

Ответ №1:

Вы можете избежать использования встроенных функций, создав дополнительный компонент и передав его обычным образом, а также передав id элемент навигации через initialParams дополнительный компонент:

 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>
  );
}
  

Итак, для этого подхода вам нужно добавить id реквизит к объектам внутри stackNavigItems :

 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} />;
    },
  },
];
  

Я опустил некоторый несвязанный код, чтобы сделать этот пример более читабельным.

Комментарии:

1. Спасибо за ответ, но это тоже не сработало.

2. Ты мой ангел!!! Сработало!!! Большое спасибо за ваше время и терпение.

3. Как вы предложили, я удалил вопрос.

Ответ №2:

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>
  );
}