React Native抽屉导航实现嵌套Accordion折叠菜单技术需求
Hey there! Let's get that nested accordion drawer menu working for your React Native app. I'll walk you through adapting your existing code to support grouped, collapsible menu items like the Outlets>Customers>Customer structure you need:
Step 1: Refactor Your Menu Data Structure
First, we need to convert your flat drawer items into a hierarchical structure. Add a children property to parent menu items to hold their sub-items:
// Updated drawer items with nested hierarchy const drawerItems = { Outlets: { navigationOptions: { drawerLabel: "Outlets" // Replace with your i18n component if needed }, userInfo: { showOnLogin: true }, children: { Customers: { navigationOptions: { drawerLabel: "Customers" }, userInfo: { showOnLogin: true }, children: { Customer: { navigationOptions: { drawerLabel: <I18nextWithTranslation i18nKey="list.title" /> }, screen: KeyboardAwareNavigator, userInfo: { showOnLogin: true } } // Add more sub-items here as needed } } } }, CreateSale: { navigationOptions: { drawerLabel: <I18nextWithTranslation i18nKey="sale.create_sale" /> }, screen: KeyboardAwareNavigator, userInfo: { showOnLogin: true } } };
Step 2: Rewrite the Drawer Component with Accordion Support
We'll replace the default DrawerItems with a custom recursive renderer that uses NativeBase's Accordion for collapsible groups. Here's the updated DrawerComponent:
import React, { useState } from 'react'; import PropTypes from 'prop-types'; import { SafeAreaView, ScrollView, StyleSheet, View } from 'react-native'; import { Container, Content, Text, List, ListItem, Accordion, Icon } from "native-base"; import { Image, ImageBackground } from "react-native"; import logo from '../images/logofullwhite200.png'; const styles = StyleSheet.create({ container: { flex: 1, paddingTop: 20 }, accordionHeader: { padding: 15, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }, accordionHeaderText: { fontSize: 16, color: '#333' }, listItem: { paddingLeft: 30 // Indent sub-menu items for visual hierarchy } }); // Recursive function to render nested menu items const renderMenuItems = (items, onItemPress, skippedItems) => { return Object.keys(items).map(key => { const item = items[key]; // Skip items marked to be hidden if (skippedItems.includes(key)) return null; // Render as Accordion if item has children if (item.children) { const [expanded, setExpanded] = useState(false); const header = ( <View style={styles.accordionHeader}> <Text style={styles.accordionHeaderText}> {typeof item.navigationOptions.drawerLabel === 'object' ? item.navigationOptions.drawerLabel : item.navigationOptions.drawerLabel} </Text> <Icon name={expanded ? 'arrow-down' : 'arrow-forward'} /> </View> ); const content = ( <List> {renderMenuItems(item.children, onItemPress, skippedItems)} </List> ); return ( <Accordion key={key} header={header} content={content} expanded={expanded} onPress={() => setExpanded(!expanded)} /> ); } // Render as regular list item if no children else { return ( <ListItem key={key} onPress={() => onItemPress({ route: { routeName: key } })} style={styles.listItem} > {typeof item.navigationOptions.drawerLabel === 'object' ? item.navigationOptions.drawerLabel : <Text>{item.navigationOptions.drawerLabel}</Text>} </ListItem> ); } }); }; const DrawerComponent = props => { const skippedItems = Object.keys(props.drawerItems).filter(name => props.drawerItems[name].skip); return ( <ScrollView style={styles.container}> <SafeAreaView style={styles.container} forceInset={{ top: 'always', horizontal: 'never' }}> <Content> <ImageBackground source={{ uri: "https://raw.githubusercontent.com/GeekyAnts/NativeBase-KitchenSink/master/assets/drawer-cover.png" }} style={{ height: 120, alignSelf: "stretch", justifyContent: "center", alignItems: "center" }} > <Image square style={{ height: 50, width: 150 }} source={logo} /> </ImageBackground> {/* Replace default DrawerItems with our custom nested renderer */} <List> {renderMenuItems(props.drawerItems, props.onItemPress, skippedItems)} </List> </Content> </SafeAreaView> </ScrollView> ); }; DrawerComponent.propTypes = { onItemPress: PropTypes.func, drawerItems: PropTypes.object }; export default DrawerComponent;
Key Changes Explained
- Recursive Menu Rendering: The
renderMenuItemsfunction traverses your hierarchical data, renderingAccordioncomponents for parent items and regular list items for child items. - Collapsible State: Each accordion uses local state (
useState) to track whether it's expanded or collapsed. - Visual Hierarchy: Sub-menu items have left padding to clearly show their nested position.
- Compatibility: The code preserves your existing i18n drawer labels and skip-item logic.
Notes
- Ensure your NativeBase version supports the
Accordioncomponent (if you're on an older version, you may need to upgrade). - You can customize the accordion header/icon styles to match your app's design system.
- Your
index.tsxconfiguration doesn't need changes—just make sure themodules.drawerItemsuses the new hierarchical structure.
内容的提问来源于stack exchange,提问作者Caner
相关产品推荐
相关产品推荐

