Simple Slide Menu with React Native

React Native is amazing. I have been using it for some time and I am preparing our first production application implemented entirely with it.

The only drawback that you might have experienced currently is that there are not that many components to work with.

Therefore you have two options if you need a particular kind of component. You can either take an existing Objective-C component and write the bridge code or you can use the existing React Native components to implement it yourself.

The first option sounds easy, and it is. The second is actually even easier. Looking at what other people have done, you will be amazed of the power of React Native and with how little code you are able to achieve really good results.

One of the missing components, which I needed for our application is a left sliding menu. This is a common pattern in todays mobile apps. Almost any app out there implements it.

What do we need?

Let’s build a simple version of it and then in another article or by yourself you can iterate and make it more complex with more features.

Accept two components, left and center.

When the center view is dragged to the right, reveal the left view underneath.

When dragged to the left the center component hides the other one.

Both left and center should be able to contain lists and scroll views without their scrolling to interfere with the revealing mechanism.

The component closes or opens automatically and with animation when the user lifts his finger.

I think this is enough to start with and most apps will be happy with it.

The Code

Let’s look at how we have implemented it in our application.

'use strict'varReact=require('react-native')var{Animation,PanResponder,StyleSheet,View,}=ReactvarDimensions=require('Dimensions')varscreenWidth=Dimensions.get('window').widthvarSlideMenu=React.createClass({componentWillMount:function(){this.offset=0// Contains the center view offset from the left edge
this._panGesture=PanResponder.create({onMoveShouldSetPanResponder:(evt,gestureState)=>{returnMath.abs(gestureState.dx)>Math.abs(gestureState.dy)&&Math.abs(gestureState.dx)>10},onPanResponderGrant:(evt,gestureState)=>this.left=0,onPanResponderMove:(evt,gestureState)=>this.moveCenterView(gestureState.dx),onPanResponderRelease:this.moveFinished,onPanResponderTerminate:this.moveFinished,})},moveCenterView:function(left){if(!this.center)returnif((this.offset+left)<0){this.left=-this.offset}else{this.left=left}this.center.setNativeProps({left:this.offset+this.left})},moveFinished:function(){if(!this.center)returnvaroffset=this.offset+this.leftif(this.offset===0){if(offset>screenWidth*0.25){this.offset=screenWidth*0.75}}else{if(offset<screenWidth*0.5){this.offset=0}}Animation.startAnimation(this.center,400,0,'easeInOut',{'anchorPoint.x':0,'position.x':this.offset})this.center.setNativeProps({left:this.offset})},render:function(){varcenterView=this.props.renderCenterView?this.props.renderCenterView():nullvarleftView=this.props.renderLeftView?this.props.renderLeftView():nullreturn(<Viewstyle={[styles.container,this.props.style]}><Viewstyle={styles.left}>{leftView}</View><Viewstyle={[styles.center,{left:this.offset}]}ref={(center)=>this.center=center}{...this._panGesture.panHandlers}>{centerView}</View></View>)},})varstyles=StyleSheet.create({container:{flex:1,},center:{flex:1,backgroundColor:'#FFFFFF',},left:{position:'absolute',top:0,left:0,bottom:0,right:0,backgroundColor:'#FFFFFF',},})module.exports=SlideMenu

How it works?

As you can see from the code above it is very short. To build the sliding menu, we only need 5 existing components from React Native.

Animation - Used to finish the center view dragging movement

PanResponder - Handle the user dragging

StyleSheet - Calculate the right size and positioning

View - Create containers for the center and left view

Dimensions - Get the screen size

There are two containers views center and left. left is at the bottom, absolutely positioned and never moves. center is on top and can be dragged to reveal the left view which is supposed to contain your menu or maybe something else, there is no real limitation of what it can be.

this.offset contains the center view offset from the left edge at the beginning of the movement while this.left contains how much has the center view been dragged from the offset.

It ensures that the center view move only begins if there is a significant horizontal dragging which is bigger than the vertical dragging.

As a result you can have a scroll view or a list view inside the center view and its dragging and scrolling will not interfere with the sliding menu.

Finally when the user is opening the screen and opens it more than 1/4 and lift his finger the rest will open automatically. Also if he closes and pass more than the half screen the rest will close by itself.

How to use it?

If you have looked closely at the code above you could see that the SlideMenu component accepts two attributes renderLeftView and renderCenterView. These should be two functions which return renderable components when called.

What is missing and can be improved

The SlideMenu component is short and simple but it can be easily improved. Here are some things I suppose I will do next and I can share it in another article.

Sliding from the right

Support simultaneously left and right menus

Support orientation change

Open/Close animated with a method call

These are just some of the things I can think of right now and I am sure you have many more ideas. You can use the code from above as your starting point if you wish.

Next

The next step for you can be to use the code I shared and try to enhance it. For me the next step is to create an even better version which can be useful and used in more cases.

Did you like this article?

Please share it

Enter your email and get our NPM Cheat Sheet for NodeJS Developers and
the links to our 5 most popular articles which have helped thousands of
developers build faster, more reliable and easier to maintain Node applications.