Notice: The Monaca & Onsen UI Community Forum is shutting down.
For Onsen UI bug reports, feature requests and questions, please use the Onsen UI GitHub issues page. For help with Monaca, please contact Monaca Support Team.
Thank you to all our community for your contributions to the forum. We look forward to hearing from you in the new communication channels.
manage splitterSide for use it as reusable component
-
Hi guys I want to create a new SideMenu component based on OnsenUI splitterSide demo I try this but I don’t know how I can manage my sates and props. I’m new in React.js. Can someone help me to fix this?
This is my component code now:import React, { PropTypes, Component } from 'react'; import { Page, Icon, List, ListItem, Splitter, SplitterSide, SplitterContent} from 'react-onsenui'; import page1 from '../pages/page1.jsx'; import page2 from '../pages/page2.jsx'; class SideMenu extends Component { constructor(props) { super(props); this.hide = this.hide.bind(this); this.show = this.show.bind(this); this.page1 = this.page1.bind(this); this.page2 = this.page2.bind(this); }; hide() { this.props.isOpen = false; }; show() { this.props.isOpen = true; }; goto_page1() { this.props.navigator.resetPage({ component: page1, key: 'Page1_Index' }); }; goto_page2() { this.props.navigator.resetPage({ component: page2, key: 'Page2_Index' }); }; render() { return ( <Splitter> <SplitterSide style={{ boxShadow: '0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)' }} side='left' width={200} collapse={true} isSwipeable={true} isOpen={this.props.isOpen} onClose={this.hide} onOpen={this.show} > <Page> <List dataSource={['page one', 'page two']} renderRow={(title) => { switch(title) { case "page one": return ( <ListItem key={title} onClick={this.goto_page1} tappable> <div>{title}</div> </ListItem> ); break; case "page two": return ( <ListItem key={title} onClick={this.goto_page2} tappable> <div>{title}></div> </ListItem> ); break; default: return ( <ListItem key={title} onClick={this.hide} tappable> <div>{title}</div> </ListItem> ); break; } }} /> </Page> </SplitterSide> <SplitterContent> {this.props.children} </SplitterContent> </Splitter> ); } } SideMenu.propTypes = { navigator: PropTypes.object }; export default SideMenu;
And this is Page1 code:
import React, { PropTypes, Component } from 'react'; import { Page, Toolbar, ToolbarButton, Icon} from 'react-onsenui'; import SideMenu from '../components/SideMenu.jsx'; class page1 extends Component { constructor(props) { super(props); this.renderToolbar = this.renderToolbar.bind(this); this.hide = this.hide.bind(this); this.show = this.show.bind(this); this.state = { isOpen: false }; }; renderToolbar() { return ( <Toolbar> <div className='left'> <ToolbarButton onClick={this.show}> <Icon icon='ion-navicon, material:md-menu' /> </ToolbarButton> </div> <div className='center'>Page One Title</div> </Toolbar> ); }; hide() { this.setState({isOpen: false}); }; show() { this.setState({isOpen: true}); }; render() { return ( <SideMenu navigator={this.props.navigator} isOpen={this.state.isOpen}> <Page renderToolbar={this.renderToolbar}> Page content here </Page> </SideMenu> ); } } page1.propTypes = { navigator: PropTypes.object }; export default page1;
Is my code style is correct?
How to prevent two time declaration ofshow
andhide
function?
-
I change my code as bellow any idea or improvement??
import { Meteor } from 'meteor/meteor'; import React, { PropTypes, Component } from 'react'; import { Page, Icon, List, ListItem, Splitter, SplitterSide, SplitterContent, Toolbar, ToolbarButton, Modal} from 'react-onsenui'; import { Random } from 'meteor/random'; import page1 from '../pages/page1.jsx'; import page2 from '../pages/page2.jsx'; class SideMenu extends Component { constructor(props) { super(props); this.renderToolbar = this.renderToolbar.bind(this); this.hide = this.hide.bind(this); this.show = this.show.bind(this); this.goto_page1 = this.goto_page1.bind(this); this.goto_page2 = this.goto_page2.bind(this); this.state = { isOpen: false }; }; renderToolbar() { return ( <Toolbar> <div className='left'> <ToolbarButton onClick={this.show}> <Icon icon='ion-navicon, material:md-menu' /> </ToolbarButton> </div> <div className='center'>{this.props.pageTitle}</div> </Toolbar> ); }; hide() { this.setState({isOpen: false}); }; show() { this.setState({isOpen: true}); }; goto_page1() { this.props.navigator.resetPage({ component: page1, key: 'Page1_Index' }); }; goto_page2() { this.props.navigator.resetPage({ component: page2, key: 'Page2_Index' }); }; render() { return ( <Splitter> <SplitterSide style={{ boxShadow: '0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)' }} side='left' width={200} collapse={true} isSwipeable={true} isOpen={this.state.isOpen} onClose={this.hide} onOpen={this.show} > <Page> <List dataSource={[ 'page one', 'page two']} renderRow={(title) => { switch(title) { case "page one": return ( <ListItem key={title} onClick={this.goto_page1} tappable> <div className='left'>{title}</div> </ListItem> ); break; case "page two": return ( <ListItem key={title} onClick={this.goto_page2} tappable> <div className='left'>{title}</div> </ListItem> ); break; default: return ( <ListItem key={title} onClick={this.hide} tappable> <div className='left'>{title}</div> </ListItem> ); break; } }} /> </Page> </SplitterSide> <SplitterContent> <Page renderToolbar={this.renderToolbar} > {this.props.children} </Page> </SplitterContent> </Splitter> ); } } SideMenu.propTypes = { navigator: PropTypes.object.isRequired, pageTitle: PropTypes.string.isRequired }; export default SideMenu;
I also change my Page1 to:
import React, { PropTypes, Component } from 'react'; import { Icon, List, ListItem, ListHeader} from 'react-onsenui'; import SideMenu from '../components/SideMenu.jsx'; class page1 extends Component { render() { return ( <SideMenu navigator={this.props.navigator} pageTitle="page 1 title"> Page content here </SideMenu> ); } } page1.propTypes = { navigator: PropTypes.object }; export default page1;
-
new version (previous reply) return this error:
Warning: flattenChildren(...): Encountered two children with the same key, `Page1_Index`. Child keys must be unique; when two children share a key, only the first child will be used. in ons-navigator (created by Navigator) in Navigator (created by App) in Appmodules.js:48127:9 uncaught exception: Splitter side is locked.(unknown)
Any suggestion?
-
@argelius @Fran-Diox @munsterlander guys can you help me to fix this issue?
Warning: flattenChildren(...): Encountered two children with the same key, `Page1_Index`. Child keys must be unique; when two children share a key, only the first child will be used. in ons-navigator (created by Navigator) in Navigator (created by App) in Appmodules.js:48127:9 uncaught exception: Splitter side is locked.(unknown)
Why children with same key exist when I use
navigator.resetPage
? Is it a bug?
What isuncaught exception: Splitter side is locked.(unknown)
?
-
Guys I need your help. :cry:
-
@cyclops24 Sorry for not responding. I do not know much about react, so I have been waiting for the Onsen team to respond. I did do some research and found these (maybe they will be of use):
http://stackoverflow.com/questions/29382526/react-js-confuse-with-two-children-with-the-same-key
-
@cyclops24 Sorry, we’ve been going to some events in Tokyo and didn’t check the forum too much.
I think you don’t need to worry about
Splitter side is locked
. It means that it’s already in use so you cannot open it twice. The error is just a rejected promise.About the keys, if I’m not mistaken
resetPage
first pushes a new page on top of the stack and then removes the rest of the pages. Therefore, if you are resetting to an already existing page it’s normal to get that error. It must be done like this because otherwise there would be a flickering in the animation.Since this state is only momentarily, perhaps you can also ignore that error. At the end of the animatino you will have unique keys so I guess that’s fine for React. I’m not an expert in React, though.
-
Thanks @munsterlander , @Fran-Diox for your reply,
@Fran-Diox unfortunatelyresetPage
not working when returnWarning: flattenChildren(...): Encountered two children with the same key,...
I test almost anything but still my SideMenu not working well after some page changes.
I don’t know why but sometimes also it’s returnTypeError: enterPage is undefined
. :cry:
-
@argelius , @munsterlander , @Fran-Diox , @eknoes
I finally success to reproduce my issue here for provide others check that.
You can see this CodePen:
https://codepen.io/anon/pen/ObRzLB?editors=0011
Open console and see this error:TypeError: enterPage is undefined
Any Suggestion? Is it a bug or my code is wrong?
-
@cyclops24 You must push pages to the navigator, nothing else.
page1
renders intoSideMenu
and that’s not a page. Just wrap it with<Ons.Page> ... </Ons.Page>
.
-
Thanks @Fran-Diox It’s fixed man. :wink:
-
@cyclops24: you might consider a more flexible alternative. By that I mean that you manage state via a parent component that automatically gets rerendered whenever you click a new menu item: https://community.onsen.io/topic/821/splitterside/3