Как добавить кнопку внутри панели навигации react (МЕЖДУ существующими кнопками)

#reactjs #react-native #react-navigation

#reactjs #react-native #react-навигация

Вопрос:

Добавить дополнительную кнопку ящика, которая не связана с маршрутом выше или ниже кнопки DrawerItemList , так же просто, как сделать:

   <Drawer.Navigator initialRouteName="Home" drawerContent={props => {
    return (
      <DrawerContentScrollView {...props}>
        <DrawerItemList {...props} />
        <DrawerItem label="Logout" onPress={() => props.navigation.navigate("Login")} />
      </DrawerContentScrollView>
    )
  }}>
    <Drawer.Screen name="Home" component={Home}/>
    <Drawer.Screen name="About" component={About} />
  </Drawer.Navigator>
  

Но теперь мне нужно добавить пользовательскую кнопку (например, для выхода из системы, с пользовательской onPress , которая не просто переходит к маршруту, но переходит к дому и вызывает пару функций) между кнопками Home и About .

Итак, мой конечный результат кнопки в отношении кнопок на ящике должен быть:

— Главная

— Пользовательский

— О

— Выход из системы

Мне нужно было бы как-то расстаться DrawerItemList , но не уверен, как.

Есть идеи, как я могу этого добиться?

Закуску можно найти здесь

(Используя react-navigation> v5)

Ответ №1:

Начнем с того, что код DrawerItemList не допускает присутствия ничего другого, кроме экранов.

Но это просто еще один компонент, который вы должны передать.

Таким образом, самый простой способ справиться с этим — создать свою собственную версию DrawerItemList с использованием исходного кода и иметь возможность передавать пользовательскую функцию onPress .

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

 import * as React from 'react';
import {
  CommonActions,
  DrawerActions,
  DrawerNavigationState,
  ParamListBase,
  useLinkBuilder,
} from '@react-navigation/native';

import { DrawerItem } from '@react-navigation/drawer';

export default function CustomDrawerList({
  state,
  navigation,
  descriptors,
  activeTintColor,
  inactiveTintColor,
  activeBackgroundColor,
  inactiveBackgroundColor,
  itemStyle,
  labelStyle,
}: Props) {
  const buildLink = useLinkBuilder();

  return state.routes.map((route, i) => {
    const focused = i === state.index;
    //Access the custom onPress that is passed as an option
    const { title, drawerLabel, drawerIcon, onPress } = descriptors[route.key].options;
  
    return (
      <DrawerItem
        key={route.key}
        label={
          drawerLabel !== undefined
            ? drawerLabel
            : title !== undefined
            ? title
            : route.name
        }
        icon={drawerIcon}
        focused={focused}
        activeTintColor={activeTintColor}
        inactiveTintColor={inactiveTintColor}
        activeBackgroundColor={activeBackgroundColor}
        inactiveBackgroundColor={inactiveBackgroundColor}
        labelStyle={labelStyle}
        style={itemStyle}
        to={buildLink(route.name, route.params)}
        onPress={
          //if onPress is available use that or call the usual navigation dispatch
          // i also passed the navigation so that we can use it in our custom calls
          onPress
            ? () => onPress(navigation)
            : () => {
                navigation.dispatch({
                  ...(focused
                    ? DrawerActions.closeDrawer()
                    : CommonActions.navigate(route.name)),
                  target: state.key,
                });
              }
        }
      />
    );
  });
}
  

И ящик будет выглядеть так, мы передаем onPress в качестве опции

  <Drawer.Navigator
    initialRouteName="Home"
    drawerContent={(props) => {
      return (
        <DrawerContentScrollView {...props}>
          <CustomDrawerList {...props} />
        </DrawerContentScrollView>
      );
    }}>
    <Drawer.Screen name="Home" component={PlaceholderPage} />
    <Drawer.Screen name="Custom" component={PlaceholderPage} options={{
      onPress:()=>alert(123)
    }}/>
    <Drawer.Screen name="About" component={PlaceholderPage} />
  </Drawer.Navigator>
  

Вы можете проверить закуску здесь
https://snack.expo.io/@guruparan/custom-button-in-drawer

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

1. Я решил использовать это решение. Это не идеально, если они когда-либо будут обновляться DrawerList в будущих версиях (вероятно), но это единственный способ с ограниченным в настоящее время API и отлично подходит для моего варианта использования. Спасибо!

2. Да, лучше посмотрите, есть ли серьезные обновления, кроме того, что это окажет минимальное влияние на drawerlist

Ответ №2:

Самый простой способ добиться этого — просто не использовать DrawerItemList вообще.

Простой пример без какого-либо оформления (см. Snack):

 <Drawer.Navigator
    initialRouteName="Home"
    drawerContent={(props) => {
      return (
        <DrawerContentScrollView {...props}>
          <Button title="Home"onPress={() => props.navigation.navigate("Home")} />
          <Button title="Custom" onPress={() => console.log('Custom Logic')} />
          <Button title="About" onPress={() => props.navigation.navigate("About")} />
          <Button title="Logout" onPress={() => console.log('CUSTOM LOGOUT FUNCTION')} />
        </DrawerContentScrollView>
      );
    }}>
    <Drawer.Screen name="Home" component={PlaceholderPage} />
    <Drawer.Screen name="About" component={PlaceholderPage} />
  </Drawer.Navigator>
  

Ответ №3:

Я сделал это в моем случае.

Добавьте это в элементы ящика

         <DrawerItem
          {...props}
          onPress={()=> {
             navigation.navigate('home');
             //.    do other things
          }} 
          label={"Custome"}
          icon={() => <Icon name="custome" size={25} color={colors.jasmine} />}
          style={props.itemStyle}
        />