Integration of materials with a user interface with a responsive router 4?

The syntax for the new rotuer syntax uses the Link component to navigate routes. But how can this be combined with materiaul-ui ?

In my case, I use tabs as the main navigation system. Therefore, theoretically, I should have something like this:

 const TabLink = ({ onClick, href, isActive, label }) => <Tab label={label} onActive={onClick} /> export default class NavBar extends React.Component { render () { return ( <Tabs> <Link to="/">{params => <TabLink label="Home" {...params}/>}</Link> <Link to="/shop">{params => <TabLink label="shop" {...params}/>}</Link> <Link to="/gallery">{params => <TabLink label="gallery" {...params}/>}</Link> </Tabs> ) } } 

But when it displays, material-ui throws an error that the Tabs child must be a Tab component. What could be the way? How do I manage an isActive tab for a tab?

Thanks in advance

+8
material-ui react-router-v4
source share
5 answers

My teacher helped me with the help of React Router 4.0 withRouter to wrap the Tabs component to enable the following history methods:

 import React, {Component} from "react"; import {Tabs, Tab} from 'material-ui'; import { withRouter } from "react-router-dom"; import Home from "./Home"; import Portfolio from "./Portfolio"; class NavTabs extends Component { handleCallToRouter = (value) => { this.props.history.push(value); } render () { return ( <Tabs value={this.props.history.location.pathname} onChange={this.handleCallToRouter} > <Tab label="Home" value="/" > <div> <Home /> </div> </Tab> <Tab label="Portfolio" value="/portfolio" > <div> <Portfolio /> </div> </Tab> </Tabs> ) } } export default withRouter(NavTabs) 

Just add a BrowserRouter to index.js and you will be fine.

+4
source share

The error you see from material-ui is that it expects the <Tab> component to appear as a direct child <Tabs> component.

Now I have found a way to integrate the link into the <Tabs> component without losing styles:

 import React, {Component} from 'react'; import {Tabs, Tab} from 'material-ui/Tabs'; import {Link} from 'react-router-dom'; export default class MyComponent extends Component { render() { const {location} = this.props; const {pathname} = location; return ( <Tabs value={pathname}> <Tab label="First tab" containerElement={<Link to="/my-firs-tab-view" />} value="/my-firs-tab-view"> {/* insert your component to be rendered inside the tab here */} </Tab> <Tab label="Second tab" containerElement={<Link to="/my-second-tab-view" />} value="/my-second-tab-view"> {/* insert your component to be rendered inside the tab here */} </Tab> </Tabs> ); } } 

To control the "active" property for tabs, you can use the value property in the <Tabs> component, and there should also be a value property for each tab, so when both properties match, it will apply the active style to this tab.

+2
source share

You can use browserHistory instead of the React-Router Link component

 import { browserHistory } from 'react-router' // Go to /some/path. onClick(label) { browserHistory.push('/${label}'); } // Example for Go back //browserHistory.goBack() <Tabs> <Tab label={label} onActive={() => onClick(label)} /> </Tabs> 

As you can see, you can simply push() your target in browserHistory

+1
source share

Here's another solution using beta Material 1.0 and adding a Browser Back / Forward to the mix:

 import React from 'react'; import PropTypes from 'prop-types'; import { withStyles } from 'material-ui/styles'; import AppBar from 'material-ui/AppBar'; import Tabs, { Tab } from 'material-ui/Tabs'; import { withRouter } from "react-router-dom"; import Home from "./Home"; import Portfolio from "./Portfolio"; function TabContainer(props) { return <div style={{ padding: 20 }}>{props.children}</div>; } const styles = theme => ({ root: { flexGrow: 1, width: '100%', marginTop: theme.spacing.unit * 3, backgroundColor: theme.palette.background.paper, }, }); class NavTabs extends React.Component { state = { value: "/", }; componentDidMount() { window.onpopstate = ()=> { this.setState({ value: this.props.history.location.pathname }); } } handleChange = (event, value) => { this.setState({ value }); this.props.history.push(value); }; render() { const { classes } = this.props; const { value } = this.state; return ( <div className={classes.root}> <AppBar position="static" color="default"> <Tabs value={value} onChange={this.handleChange} scrollable scrollButtons="on" indicatorColor="primary" textColor="primary" > <Tab label="Home" value = "/" /> <Tab label="Portfolio" value = "/portfolio"/> </Tabs> </AppBar> {value === "/" && <TabContainer>{<Home />}</TabContainer>} {value === "/portfolio" && <TabContainer>{<Portfolio />}</TabContainer>} </div> ); } } NavTabs.propTypes = { classes: PropTypes.object.isRequired, }; export default withRouter(withStyles(styles)(NavTabs)); 
+1
source share

Since @gkatchmar says you can use the high-order withRouter component, but you can also use the context API . As @gkatchmar showed with Router, I will show only the context API . Keep in mind that this is an experimental API.

stack overflow

 import React, {Component} from "react"; import {Tabs, Tab} from 'material-ui'; import * as PropTypes from "prop-types"; export class NavTabs extends Component { constructor(props) { super(props); } static contextTypes = { router: PropTypes.object } handleChange = (event: any , value: any) => { this.context.router.history.push(value); }; render () { return ( <Tabs value={this.context.router.history.location.pathname} onChange={this.handleChange} > <Tab label="Home" value="/" > <div> <Home /> </div> </Tab> <Tab label="Portfolio" value="/portfolio" > <div> <Portfolio /> </div> </Tab> </Tabs> ) } } 
0
source share

All Articles