Hi!
I'm trying to create a navigation drawer that will point his text elements to jump between screens.
For the matter, I'm using react-native-drawer by root-two.
Do you have any example or can give me some direction of how to combine those two? I can't seem to figure that out.
Thanks!
It is interesting question, have you tried set Drawer as 'footer' prop for Router?
+1
Any progress on this? I am trying to use react-native-side-menu module with this router-flux. Actually it only works until i try to call any Actions.
My SideMenu combined with router-flux:
<SideMenu
menu={<Menu/>}
isOpen={false} >
<Router hideNavBar={true}>
<Schema name="modal" sceneConfig={Navigator.SceneConfigs.FloatFromBottom}/>
<Schema name="default" sceneConfig={Navigator.SceneConfigs.FloatFromBottomAndroid}
titleStyle={{color: 'white'}}
backButtonStyle={{tintColor: 'white'}}
navigationBarStyle={{backgroundColor: Colors.MAIN}}
barButtonText={{color: 'white'}} />
<Schema name="searchbar" sceneConfig={Navigator.SceneConfigs.FloatFromRight}
titleStyle={{color: 'white'}} backButtonStyle={{tintColor: 'white'}}
navigationBarStyle={{backgroundColor: Colors.MAIN}}/>
<Route name="launch" component={Launch}/>
<Route name="dashboard">
<Router hideNavBar={false}>
<Route name='home' component={Dashboard} title={Strings('home')} type='replace'
renderTitle={renderTitle}/>
..........
..........
It works up to the point when i try calling any actions from the Side Menu, where unfortunately nothing happens.
A Button in my Side Menu, which should call Home Screen:
<Button onPress={Actions.home}>
<View style={styles.row}>
<Image style={styles.itemImage} source={require('../Assets/SideMenu/home_off.png')}/>
<Text style={styles.itemText}>Home</Text>
</View>
</Button>
Any ideas why Actions won麓t work?
Try {()=>Actions.home()} because Actions.home may not defined during compile time...
Okay nice, it fixed it thanks. Now when i try to put my Side Menu over a nested Router, something like:
<Router hideNavBar={true}>
<Schema ......
<Route name="launch" component={Launch}/>
<Route name="dashboard" component={Dashboard}/>
<SideMenu
menu.....>
<Router hideNavBar={false}>
<Route name='home' component={Dashboard} title={Strings('home')} type='replace'
renderTitle={renderTitle}/>
<Route ...../>
<Route ...../>
<Route ...../>
</Router>
</SideMenu>
<Route ...../>
<Route ...../>
</Router>
It throws me this error when i try to call an Action:

And the NavigationBar loses it麓s Styling...
SideMenu should pass its 'router' prop to his children, otherwise router hierarchy would be broken.
Worked, thanks!
Hi @BigPun86 can you share your code? I'm trying to build similar logic with a nested tabbar. @sibeliusseraphini
An example would be helpful.
+1
It took me awhile but I got to the bottom of this.
My top level render looks like this.
<Router>
<Route name="without-drawer"/>
<Route name="main">
<Drawer>
<Router>
<Route name="with-drawer-a"/>
<Route name="with-drawer-b"/>
</Router>
</Drawer>
</Route>
</Router>
My drawer's render function looks like this.
<DrawerLayout>
{React.Children.map(children, c => React.cloneElement(c, {route: this.props.route}))}
</DrawerLayout>
Hey there. This is how i use the Drawer/SideMenu. In my Main Router i setup as usual my routes. Then i have a nested router Dashboard where i need the Drawer/SideMenu
<Router hideNavBar={true}>
<Schema name="modal" sceneConfig=......................./>
<Schema name="default" sceneConfig=.............../>
<Schema name="searchbar" sceneConfig=.............../>
<Route name="dashboard" schema="dashboard">
<Router hideNavBar={false}>
<Route name='home' component={ Routes.Dashboard } title={translate('dashboard')} type='reset'
renderTitle={renderTitle}/>
<Route name="chatAndGroups" component={ Routes.ChatAndGroups } title={translate('myGroups')}
renderTitle={renderTitle} renderLeftButton={renderBackButton}/>
<Route name="reviews" component={ Routes.Reviews} title={translate('reviews')}
renderTitle={renderTitle}
renderLeftButton={renderBackButton}/>
<Route name="weather" component={ Routes.Weather} title={translate('weather')}
renderTitle={renderTitle}
renderLeftButton={renderBackButton}/>
</Router>
</Route>
<Route name="launch" component={Routes.Launch} initial={true}/>
<Route name="tutorial" component={Routes.Tutorial}/>
<Route name="disclaimer" component={ Routes.Disclaimer} title={translate('disclaimer')}
renderTitle={renderTitle}
renderLeftButton={renderBackButton}/>
<Route name="login" component={ Routes.Login} title={translate('login')} showNavigationBar={false}
renderLeftButton={renderBackButton}/>
<Route name="register" component={ Routes.Register} title={translate('createAccount')}
renderLeftButton={renderBackButton}/>
</Router>
)
}
In my Dashboard component i implemented the SideMenu:
export default class Dashboard extends Component {
constructor(props) {
super(props);
}
render() {
return (
<SideMenu
menu={<Menu />}
isOpen={false}
>
<ContentView/>
</SideMenu>
)
}
}
@BigPun86 do you have a repo for this ? How does the navigator know to render your scene in
Thank you @BigPun86, your solution is working for me.
If anyone needs an example I used the sidebar in this common pattern:
Router.js
export default class Routes extends React.Component {
render() {
return (
<Router>
<Route component={SessionScreen} name='session' type='replace' hideNavBar={true} initial={true} />
<Route component={AuthScreen} name='auth' type='replace' />
<Route name='main' hideNavBar={true} type='reset'>
<SideDrawer>
<Router>
<Route component={PlaceScreen} name='place' title='Place' />
<Route component={ItemScreen} name='item' title='Item' />
...
</Router>
</SideDrawer>
</Route>
</Router>
)
}
}
SideDrawer.js (I'm using 'react-native-drawer')
import Drawer from 'react-native-drawer'
class SideDrawer extends React.Component {
render() {
return (
<Drawer
type="overlay"
content={<SideDrawerContent />}
tapToClose={true}
openDrawerOffset={0.2}
panCloseMask={0.2}
closedDrawerOffset={-3}
styles={{ drawer: drawerStyle, main: mainStyle }}
tweenHandler={(ratio) => ({ main: { opacity: (2 - ratio) / 2 } })}
>
{React.Children.map(this.props.children, c => React.cloneElement(c, {
route: this.props.route
}))}
</Drawer>
)
}
}
Be careful of #172 that you can fix by adding in AuthScreen.js:
componentWillUnmount() {
// Fix https://github.com/aksonov/react-native-router-flux/issues/172
Actions.currentRouter = null
}
@mmazzarolo nice example. I tried yours which works for me too even better than mine. But how do you pass the schema to the children? I tried this:
{React.Children.map(this.props.children, c => React.cloneElement(c, {
route: this.props.route,
schema: this.props.schema
}))}
This is what worked to pass the navigationBarStyle, but i am not sure if passing the schema would be nicer...:
{React.Children.map(this.props.children, c => React.cloneElement(c, {
route: this.props.route,
navigationBarStyle: this.props.navigationBarStyle
}))}
Thank you @BigPun86!
You don't need to pass the schema/styles to the children:
Router.js
const hideNavBar = Platform.OS === 'android'
const paddingTop = Platform.OS === 'android' ? 0 : 8
export default class Routes extends React.Component {
render() {
return (
<Router>
<Schema
name='boot'
sceneConfig={Navigator.SceneConfigs.FadeAndroid}
hideNavBar={true}
type='replace'
/>
<Schema
name='main'
sceneConfig={Navigator.SceneConfigs.FadeAndroid}
hideNavBar={hideNavBar}
/>
<Route schema='boot' component={SessionScreen} name='session' initial={true} />
<Route schema='boot' component={AuthScreen} name='auth' />
<Route name='main' hideNavBar={true} type='reset'>
<SideDrawer>
<Router
sceneStyle={styles.scene}
navigationBarStyle={styles.navigationBar}
titleStyle={styles.title}
barButtonIconStyle={styles.barButtonIcon}
barButtonTextStyle={styles.barButtonText}
>
<Route schema='main' component={PlaceScreen} name='place' title='Places' />
<Route schema='main' component={PaymentScreen} name='payment' title='Payment' header={Toolbar} />
</Router>
</SideDrawer>
</Route>
</Router>
)
}
}
The router above is working for me, hope it helps.
thanks @mmazzarolo for the well-structured code. That ended up working for me better than my hackish implementation of the drawer!!!
@mmazzarolo Good work! Could you please add this as section to README?
hey @aksonov got a quick moment to hop onto Gitter?
Thanks @MITDelian, but I just stolen and implemented the idea from @GarrettSmith's comment.
@aksonov can you take a look at #69 ? I can be helpful with the README/wiki if you want!
@mmazzarolo
I've tried setting up your example. When I call Actions.main (the route with the drawer) I get undefined is not a function this._navBar.immediatelyRefresh()
Sorry for bringing this up again!
If I wrap a Router in the
Any ideas? @mmazzarolo
Not sure what u mean exactly...But this is how i implemented my Router with SideMenu (react-native-drawer)
.............................
<SideDrawer ref="drawer" router={this.refs.router}>
<Router
ref="router"
firstRoute={{
.......................
export default class SideDrawer extends Component {
constructor(props) {
super(props);
}
render() {
var userToken = store.getState().User.token;
return (
<Drawer
ref="drawer"
type="overlay"
content={<Menu {...this.props} />}
tapToClose={true}
openDrawerOffset={0.2}
panCloseMask={0.2}
closedDrawerOffset={0}
tweenHandler={(ratio) => ({ main: { opacity: (2 - ratio) / 2 } })}
disabled={ userToken === '' || userToken === null || userToken === undefined }
>
{React.Children.map(this.props.children, c => React.cloneElement(c, {
route: this.props.route
}))}
</Drawer>
)
}
}
The main thing is to give your router and sidedrawer a ref and you can than acces the trigger for opening closing from anywhere like this:
this.refs.drawer.refs.drawer.open();
Hmm yeah that is strange you see..
My Main Component:
class App extends Component {
render() {
return (
<Router key='mainrouter' name='router' sceneStyle={ styles.router }>
<SideDrawer key='drawer' ref='drawer' router={ this.refs.router }>
<Router ref='router' key='root' duration={ 100 }>
<Scene key='home' initial={ true } component={ Home } hideNavBar={ true } />
</Router>
</SideDrawer>
</Router>
);
}
}
My SideDrawer:
export default class SideDrawer extends Component {
render () {
return (
<Drawer
ref='drawer'
type={'overlay'}
content={<ControlPanel />}
openDrawerOffset={ (viewport) => viewport.width - 250 }
tweenDuration={ 100 }
tapToClose={ true } >
{React.Children.map(this.props.children, c => React.cloneElement(c, {
route: this.props.route
}))}
</Drawer>
)
}
};
And my 'home' component where I try to open and close the drawer:
render() {
return (
<TouchableOpacity onPress={ () => this.refs.drawer.open() }>
<Text>Open Drawer</Text>
</TouchableOpacity>
)
}
But if I click the TouchableOpacity I get a cannot read property open of undefined.
(I have tried this.res.drawer.refs.drawer.open as well - but I thought it was a typo?)
Any ideas?
@davidfloegel do you have Discord? So we could solve it there....
Just got an account! davidfloegel is my username!
Hi,
I have used react-native-router-flux and react-native-drawer together. Can anybody help me to show drawer only for dashboard screen not for login.
There is some way to use react-native-router-flux and react-native-side-menu together, using the latest version of both? Seems like all these answers are outdated.
This is my code. It works at the main Scene, but as you go to the others it everything goes blank (the side bar actually still works at that part).
const RouterComponent = () => {
return (
<SideMenu menu={<Menu navigator={navigator}/>}>
<Router>
<Stack key="teams">
<Scene key="league_list" component={LeagueList} title="Leagues" initial />
<Scene key="team_list" component={TeamList} title="Teams" />
<Scene key="soloteam" component={Team} />
</Stack>
</Router>
</SideMenu>
);
};
Most helpful comment
Try {()=>Actions.home()} because Actions.home may not defined during compile time...