React-native-navigation: [V2] toggleDrawer does not exist?

Created on 2 Jul 2018  路  13Comments  路  Source: wix/react-native-navigation

Issue Description

Due to the lack of docs I can't find a way to open sideMenu on button press in V2.
In v1 vs v2 feature comparison it says toggleDrawer is available in v2, but there is no sign of it in V2 docs.

Steps to Reproduce / Code Snippets / Screenshots

Navigation.setRoot({
    root: {
      sideMenu: {
        left: {
          component: {
            name: 'testApp.SideDrawer',
          }
        },
        center: {
          bottomTabs: {
            ...
          }
        },
      },
    },
});

Environment

  • React Native Navigation version: 2.0.2381
  • React Native version: 0.53.0

Most helpful comment

Unfortunately the toggleDrawer is not available in the v2 you can set a variable and play with a simple if condition to toggle the drawer. Below is the working example for this using mergeOptions.

On your component, bind the navigationButtonPressed and then

`constructor(props) {
super(props);
this.isSideDrawerVisible = false;
Navigation.events().bindComponent(this);
}

navigationButtonPressed({ buttonId }) {
if (buttonId === "openSideDrawer") {
(!this.isSideDrawerVisible) ? this.isSideDrawerVisible = true : this.isSideDrawerVisible = false
Navigation.mergeOptions(this.props.componentId, {
sideMenu: {
left: {
visible: this.isSideDrawerVisible,
}
}
});
}
}`

All 13 comments

You can make the drawer "visible" to show it:

Navigation.mergeOptions('navigation.drawer.left', {
    sideMenu: {
      left: {
        visible: true
      }
    }
  });

Ok, that worked (used drawer componentId from debugger).
Any idea how to get drawer componentId if I call mergeOptions from another screen component?

You can easily supply your own componentId:

Navigation.setRoot({
    root: {
      sideMenu: {
        left: {
          component: {
                         id: 'leftSideComponentId`,
            name: 'testApp.SideDrawer',
          }
        },
        center: {
          bottomTabs: {
            ...
          }
        },
      },
    },
});

Really appreciating that this package supports both left and right-sided drawers, but this "functionality" really needs to be explained better in the docs, since it currently misrepresents that toggleDrawer is a valid method in v2. Hours spent on a wild goose-chase is no fun, thank goodness for github issues or it could have been back to react-navigation.

toggledrawer

Would offer to do a pull for the doc update, however, not sure if the plan to eventually ADD toggleDrawer() to v2, or will this visibility remain the recommended functionality for drawer toggling?

It would be really nice to have the toggleDrawer functionality. If it is there and I am missing it please let me know.

We really need a toggleDrawer function, like it was in Version 1, so we will be able to open/close drawer in any time, not only with pushes.

Is there a place where sideMenu.left.visible and sideMenu.right.visible are exposed, or can we somehow 'listen' to visibility changes? Without one of those, I don't see how we can write a toggle method. If a user opens or closes the sideMenu through an onPress event, we can keep that in the state, but if the sideMenu is dragged open, or dragged closed, it seems we're left hanging.

Here's a quick and dirty way you can use registerComponentDidAppearListener and registerComponentDidDisappearListener to listen for visibility changes.

constants.js

const LEFT_SIDE_MENU_ID = 'navigation.drawer.left';
const RIGHT_SIDE_MENU_ID = 'navigation.drawer.right';

export {
  LEFT_SIDE_MENU_ID,
  RIGHT_SIDE_MENU_ID,
};

Drawer.js

import { Navigation } from 'react-native-navigation';
import { LEFT_SIDE_MENU_ID, RIGHT_SIDE_MENU_ID } from '../constants';

function getId(side) {
  if (side === 'left') return LEFT_SIDE_MENU_ID;
  return RIGHT_SIDE_MENU_ID;
}

class Drawer {
  constructor() {
    this.visibility = {
      left: false,
      right: false,
    };

    Navigation.events().registerComponentDidAppearListener(({ componentId }) => {
      if (componentId === LEFT_SIDE_MENU_ID) {
        this.visibility.left = true;
      }

      if (componentId === RIGHT_SIDE_MENU_ID) {
        this.visibility.right = true;
      }
    });

    Navigation.events().registerComponentDidDisappearListener(({ componentId }) => {
      if (componentId === LEFT_SIDE_MENU_ID) {
        this.visibility.left = false;
      }

      if (componentId === RIGHT_SIDE_MENU_ID) {
        this.visibility.right = false;
      }
    });
  }

  // side: String ('left', 'right')
  open(side) {
    try {
      const id = getId(side);
      Navigation.mergeOptions(id, {
        sideMenu: {
          [side]: {
            visible: true,
          },
        },
      });
      this.visibility[side] = true;
    } catch (error) {
      //
    }
  }

  // side: String ('left', 'right')
  close(side) {
    try {
      const id = getId(side);
      Navigation.mergeOptions(id, {
        sideMenu: {
          [side]: {
            visible: false,
          },
        },
      });
      this.visibility[side] = false;
    } catch (error) {
      //
    }
  }

  // side: String ('left', 'right')
  toggle(side) {
    try {
      const id = getId(side);
      const visibility = !this.visibility[side];
      Navigation.mergeOptions(id, {
        sideMenu: {
          [side]: {
            visible: !this.visibility[side],
          },
        },
      });
      this.visibility[side] = visibility;
    } catch (error) {
      //
    }
  }
}

export default new Drawer();

Then you can use it like this:

import Drawer from './Drawer';

Drawer.open('left');
Drawer.close('right');
Drawer.toggle('left')

how can I show drawer over on center in IOS?

i have the same issue, the message is "Cannot read property 'toggleDrawer' of undefined ", any update about this. thanks in advance!

same issue

Unfortunately the toggleDrawer is not available in the v2 you can set a variable and play with a simple if condition to toggle the drawer. Below is the working example for this using mergeOptions.

On your component, bind the navigationButtonPressed and then

`constructor(props) {
super(props);
this.isSideDrawerVisible = false;
Navigation.events().bindComponent(this);
}

navigationButtonPressed({ buttonId }) {
if (buttonId === "openSideDrawer") {
(!this.isSideDrawerVisible) ? this.isSideDrawerVisible = true : this.isSideDrawerVisible = false
Navigation.mergeOptions(this.props.componentId, {
sideMenu: {
left: {
visible: this.isSideDrawerVisible,
}
}
});
}
}`

For me, surprised that this toggles the sideMenu not just opens it:

Navigation.mergeOptions({
    sideMenu: {
         left: {
             visible: true
        }
    }
});
Was this page helpful?
0 / 5 - 0 ratings