Impossible to have two menu on the same screen
Asked Answered
J

1

6

The goal

I'm trying to achieve a screen that looks like this. There are two menus, one is the burger menu created by createDrawerNavigator from react-navigation (top left corner). The other menu is the bottom button created by createBottomTabNavigator.

Yes having two menus isn't a good UI choice, but that's my company's choice .. Moreover these menus share at least one entry (homepage).

enter image description here enter image description here

What did I try

This stackoverflow was pretty close of the awaited result, but I can't figure out how to display the burger menu and not a simple view like the post does.

I tried multiple hierarchy structures without success to accomplish exactly the goal.

So I was out of ideas and I decided to accomplish the bottom menu on my own. It seems to work well, but some routes aren't defined so I can't navigate to them (like cart and search on my screen)

It seems that react-navigation uses its component to define the routes.

The question

How can I add routes to the navigation system in order to be able to navigate to them?

I tried :

  • Specifying an initialState to the <NavigationContainer> but it doesn't seem to work.

  • Created a custom router to overwrite the getInitialState method, but I can't figure out how to use my custom router after that!

Any help will be greatly appreciated

Edit:

The navigation code

// src/menu/burger/drawer.js
import { createDrawerNavigator } from '@react-navigation/drawer';
import { useTranslation } from 'react-i18next';
import Ionicons from '@expo/vector-icons/Ionicons';
import React from 'react';

import Account from '../../pages/account';
import Brands from '../../pages/brands';
import Cart from '../../pages/cart';
import Homepage from '../../pages/homepage';
import {
  ACCOUNT,
  BRANDS,
  CART,
  HOMEPAGE,
} from '../../pages/pageIdentifiers';

const Drawer = createDrawerNavigator();
const renderMenuIcon = (iconName, size, focused) => (
  <Ionicons
    name={iconName}
    size={size}
    color={focused ? '#7cc' : '#ccc'}
  />
);

// This component render the items of the burger menu displayed in the top left corner
export default function MenuDrawer() {
  const { t } = useTranslation();

  return (
    <Drawer.Navigator
      initialRouteName={HOMEPAGE}
    >
      <Drawer.Screen
        name={HOMEPAGE}
        component={Homepage}
        options={{
          title: t('menu.item.homepage'),
          drawerIcon: ({ focused, size }) => renderMenuIcon('md-home', size, focused),
        }}
      />
      <Drawer.Screen
        name={CART}
        component={Cart}
        options={{
          title: t('menu.item.cart'),
          drawerIcon: ({ focused, size }) => renderMenuIcon('cart-outline', size, focused),
        }}
      />
      <Drawer.Screen
        name={ACCOUNT}
        component={Account}
        options={{
          title: t('menu.item.account'),
          drawerIcon: ({ focused, size }) => renderMenuIcon('person-outline', size, focused),
        }}
      />
      <Drawer.Screen
        name={BRANDS}
        component={Brands}
        options={{
          title: t('menu.item.brands'),
          drawerIcon: ({ focused, size }) => renderMenuIcon('basket-outline', size, focused),
        }}
      />
    </Drawer.Navigator>
  );
}


// App.js
export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <MenuDrawer />
        <BottomTabsMenu />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

// src/menu/bottomTabs/drawer.js
// We can't use 2 menus with 2 differents navigators on the same view.
// So let's handle the click on tabs ourselves
export default function BottomTabsMenu() {
  const [activeTab, setActiveTab] = useState(HOMEPAGE);
  const navigation = useNavigation();
  // useEffect(() => {
  //   const subscription = navigation.addListener('focus', (data) =>  {
  //     console.log(data);
  //   });
  //   return subscription;
  // }, [navigation]);
  
  // This function crash when the route id is not known by react-navigation, well logic
  const onMenuPress = (id) => {
    navigation.navigate(id);
    setActiveTab(id);
  };

  return (
    <View style={styles.container}>
      {bottomMenuItems.map(
        (menuItem) => (
          <View
            key={`view-${menuItem.id}`}
            style={styles.item}
          >
            <MenuItem
              key={`menu-${menuItem.id}`}
              isFocus={menuItem.id === activeTab}
              onPress={(id) => onMenuPress(id)}
              configuration={menuItem}
            />
          </View>
        )
      )}
    </View>
  );
}
Jeunesse answered 6/9, 2022 at 9:5 Comment(2)
Can you add your navigation code as wellRomance
@Romance I added the navigation codeJeunesse
B
2

https://snack.expo.dev/BsCtDUFoM (minimized)
https://snack.expo.dev/Zgn9M59H7 (full/og)

Web: both navigators/menus are perfectly synced when you navigate

(edit: got it working perfectly for android and ios)

code is really messy but I'm not sure how to clean it up

Bolten answered 21/9, 2022 at 6:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.