I'm using Meteor, React and Material-UI to create an app. To keep it simple, let's say that the app has two pages: home and user.
Both pages should have the same layout: an AppBar with a hamburger menu on the left and an IconMenu on the right. When the hamburger menu is selected a Drawer will slide out from the left, and when the right menu is selected a drop-down menu will appear.
For my purposes the drawer menu is static, i.e. the menu entries don't change depending on what page (home or user) is being displayed. The drop-down menu on the right, however, will change depending on what page is active, i.e. it's context-sensitive.
My question is: what options do I have in terms of building this?
I think one option is to create two page components, e.g. HomePage and UserPage, and compose each using e.g. MyAppBar and MyDrawer, plus whatever content the specific page should contain. Each page would then be responsible for creating the menu items on the drop-down menu and passing them to MyAppBar and then the entire page would be rendered.
I believe this would solve the problem, but I'm not sure if there is a better way. For instance, is there a second approach where I could update just the content component of the page and have the owning component (e.g. an ApplicationPage component) query the content component (e.g. HomeContent or UserContent) for the entries of the drop-down menu and set the drop-down menu when there's a content component change? Any other options?
I'm using React Router to do routing for /home and /user so the above must also fit in with that.
I use react router for this purpose.
<Router history={browserHistory}>
<Route component={App}>
<Route path='/login/' components={{main: Login}} />
<Route path='/confirm'
components={{
main: Confirm,
sidebar:Sidebar
}}
/>
</Route>
</Router>
In the Template App, we can then use this.props.main and this.props.sidebar as variables.
Please look at https://github.com/reactjs/react-router/blob/master/examples/sidebar/app.js form more details.
Related
I have started playing a bit with Shopify Polaris, in particular, the Frame layout:
https://polaris.shopify.com/components/structure/frame
What is not clear to me is that in the example provided by Shopify the sidebar, when an item is clicked, always toggles the toggleIsLoading method, and then it eventually always renders the actualPageMarkup component.
However, I would like to have a sidebar menu containing n different items. For each of them, I would like to render a particular component associated with the selection. How can I achieve this?
Ideally, I would like to always display the sidebar and the header, no matter what the component is.
I understand this question is not strictly related to Shopify Polaris or Next.js, however, I consider myself a newbie in both React and Next.js.
My overall goal is something like this for the main overarching layout component:
Live example of my goal: https://app.mobalytics.gg/
Where there is a persistent 'sticky' top bar and side bar at all stages of the application. And then from that point on I use my router to modify the white portion of the screenshot with whatever component / functionality I want the user to experience.
However I am unfortunately struggling to get this to work at all. Various attempts have resulted in navbar overlapping the sidebar and then others the sidebar overlapping the navbar, some attempts crushed the sidebar to basically be only as long as the navbar. Tried using grids and then that crushed the "white portion" when I added components through the router and a few other non-solutions sadly...
How would someone achieve this with semantic-ui-react?
Other answers I've looked at and tried to no success sadly:
1: Separating Top Nav bar and Side nav bar
2: Sidebar + Fixed Top Menu in Semantic-UI React
3: semantic-ui-react fixed sidebar and navbar: can't get sidebar and content to scroll nicely
I'm trying to better understand how Material-UI works, and I was confused why I need to use the Toolbar component twice to get my scrolling toolbar to render properly as in this example code.
If I don't include the second Toolbar after the ElevationScroll, the menu I want to place below the app bar is rendered underneath the app bar. If I include it, my menu is pushed down and renders nicely. This works great, but I don't understand why I need to include an extra in my jsx in order to get things to look right, like in this simplified example:
function SettingsMenu() {
return (
<ElevationScroll>
<AppBar>
<Toolbar>
<Typography>
Settings
</Typography>
</Toolbar>
</AppBar>
</ElevationScroll>
<Toolbar/>
<MyMenu/>
);
}
I've checked in Google Devtools to figure out why this is happening, the second toolbar is rendered as a div with nearly identical css styles but with no child elements. When I delete it manually in Devtools, the menu gets pushed back up behind the app bar as before. Thanks for any help!
It's because AppBar have positon: fixed; which means it wont take space on the screen so you but another Toolbar which will be underneath the AppBar to push the content down and take the same space the Toolbar should take.
Let's say I have a React app (with React Router 4) with the following components and routes:
App (/)
Toolbar - A fixed toolbar
NavButton - A button whose appearance and behavior depends on the current route (see below)
MainMenu - A temporary drawer that pops out from the side to navigate between top-level routes
Admin (/admin)
Sidenav - A navigation drawer that is open all of the time on large screens and can be toggled on small screens. Clicking on items in the Sidenav navigates to different sub-routes under /admin
Content (/admin/<xyz>)
Public (/public)
Content
The behavior of the NavButton should be the following:
On a large screen:
it should always be a hamburger icon that opens the MainMenu.
On a small screen: (except for the first condition, this is similar to the experience on the Gmail mobile app)
if there is no Sidenav, it should display a hamburger icon that opens the MainMenu.
if the Sidenav is closed, it should display a back icon that opens the Sidenav.
if the Sidenav is open, it should display a hamburger icon that opens the MainMenu.
The /admin and /public routes are just examples. There are many more, some of which have Sidenavs and some of which don't.
My question is this: what is the React way to manage the UI state here and wire all of the components and routes together? It feels like App should be responsible for keeping track of whether the sidenav is open, so it can pass that information to Toolbar and others, but it also seems like App shouldn't be in charge of managing which of its potential children have or don't have Sidenavs. Also, how can props get passed down from App to some child when there's a Route in between?
Note: I'm fairly new to React and certainly not married to the component structure above; it's just for illustration.
It feels like App should be responsible for keeping track of whether the sidenav is open
True. The child components should always be presentational (pure/dumb) components.
App shouldn't be in charge of managing which of its potential children have or don't have Sidenav
I wouldn't call it "in charge". It is simply keeping the state of the application. The user is in charge, by clicking the hamburger button.
how can props get passed down from App to some child when there's a Route in between?
Why not? You can use render instead of component. For example:
let Parent = (props)=> {
<Route
path="/pizza"
render={()=> <Pizza topping={props.topping} />} />
}
I'm trying to use react router to provide routes for popup windows on my site.
I have core 'dashboard' on which users can click links which open a window above the core dashboard (so the dashboard can be seen beneath the window).
When reading the documentation for react-router I thought this kind of layout was the exact use-case for nested routes but it doesn't seem to be working.
I am testing by having the window be represented by a div with a background color so I can see it.
My routes are configured as such:
<Route handler={Application}>
<Route name='dashboard' path='dashboard' handler={Dashboard} >
<Route path='window/:id' handler={Window} />
</Route>
</Route>
What I expect is that the div appears when I visit /dashboard/window/1 but nothing changes, and looking at the DOM the window div is not even rendered.
Any help would be great.
Thanks
Inside the component that you want to nest the view in you need to add a <RouteHandler /> so that the view is displayed nested in that component. We did something similar but with tabs and wanted to just change the body of the tab and the highlighted tab to get the same effect.
In React Router 1.0 you simply need to add the following to your Dashboard.render tree:
{this.props.children}