I\'m struggling to add component to my material-ui AppBar
This is my navigation class:
class Navigation extends Component
So my work-around for this solution has been quite reliable, though it may be more manual of a solution than what you're looking to do.
The strategy that I've been using is to actually not even use the Link Component. Instead, you'll utilize the Tabs onChange property as a callback that can respond to Tab clicks, and track location manually with Props on the Parent.
You can import a utility called History from react-router that will allow you to manually push locations. While using React-Router, your component tree will have access to Location prop that has a pathname key with the string of your current location.
We will manually parse this string into the components that make up your current URL, then use a Switch statement to decide both which tab is currently selected and also where to link to when a tab is clicked. (This gives you a fair amount of control over navigation)
( e.g. ['', 'latest'] )
Here is a mock up of what your component MAY look like after integrating this solution.
import React from 'react';
import {History} from 'react-router';
function parseLocation(location) {
if (String(location)) {
var locationArray = location.split('/');
return locationArray;
} else {
return false;
}
};
function filterPath(path) {
let locationArray = parseLocation(path);
return locationArray[locationArray.length - 1];
};
var Navigation = React.createClass({
mixins: [History],
getPage() {
if (this.props.location.pathname) {
let pathname = this.props.location.pathname;
let pageName = filterPath(pathname);
return pageName;
} else {
return false;
}
},
decideContent() {
let page = this.getPage();
let content;
switch(page) {
case 'popular':
content = 0;
case 'latest':
content = 1;
case 'myideas':
content = 2;
default:
content = 0;
}
return content;
},
handleTabChange(value) {
let location = false;
switch (value) {
case 0:
location = 'popular';
break;
case 1:
location = 'latest';
break;
case 2:
location = 'myideas';
break;
}
if (location && location !== this.getPage()) {
this.history.pushState(null, '/'+location);
}
},
render() {
var styles = {
appBar: {
flexWrap: 'wrap'
},
tabs: {
width: '100%'
}
};
let content = this.decideContent();
let tabs = <Tabs
onChange={this.handleTabChange}
value={content}
>
<Tab label="Most Popular Ideas" value={0} />
<Tab label="Latest Ideas" value={1} />
<Tab label="My Ideas" value={2} />
</Tabs>;
return (
<AppBar showMenuIconButton={false} style={styles.appBar}>
{tabs}
</AppBar>
);
}
});
For those who look for the TypeScript implementation. Easy configurable. Driven by tabs
configuration.
interface ITabsPageProps {
match: match<{page: string}>;
history: History;
}
const tabs = [{
label: 'Fist Tab',
link: 'fist-tab',
component: <FirstTabContent/>
}, {
label: 'Second Tab',
link: 'second-tab',
component: <SecondTabContent/>
}, {
label: 'Third Tab',
link: 'third-tab',
component: <ThirdTabContent/>
}];
export class TabsPage extends React.Component<ITabsPageProps> {
handleChange(tabLink: string) {
this.props.history.push(`/tabs-page/${tabLink}`);
}
render() {
const currentTab = this.props.match.params.page;
const selectedTab = tabs.find(tab => currentTab === tab.link);
return (
<Fragment>
<Tabs
value={currentTab}
onChange={(event, value) => this.handleChange(value)}
>
{tabs.map(tab => (
<Tab
key={tab.link}
value={tab.link}
label={tab.label}
/>
))}
</Tabs>
{selectedTab && selectedTab.component}
</Fragment>
);
}
}
You can try this simple method
<Tab label='Most popular ideas' to='/myPath' component={Link} />
This is solved using the <Link />
from material-ui instead of directly using the <Link />
or <NavLink />
from react-router. The example for the same can be found in the documentation here.
https://material-ui.com/components/links/
Also <Button />
tag has a component prop to achieve this
<Button color="inherit" component={Link} to={"/logout"}>Logout</Button>
An extensive discussion on this can be found here
https://github.com/mui-org/material-ui/issues/850
For Material UI 1.0 with Typescript: see this post by @ogglas below.
For Material-UI 1.0 with plain JS:
<Tabs value={value} onChange={this.handleChange}>
{
this.props.tabs.map(
({label, path})=><Tab key={label}
label={label}
className={classes.tabLink}
component={Link}
to={path} />
)
}
</Tabs>
And classes.tabLink
is defined as:
tabLink : {
display:"flex",
alignItems:"center",
justifyContent:"center"
}
All the mui 1.0 components inheriting from ButtonBase
, support a component
prop, see ButtonBase. The idea is to allow you to control what the component renders as its wrapper/root element. Tab
also has this feature although at the time of writing this answer this prop is not documented explicitly, but as Tab
inherits from ButtonBase
, all its props carry over (and the documentation does cover this).
Another feature of ButtonBase
is that all the extra props, not in use by ButtonBase
or inherited component, are spread over the specified component
. We have used this behavior to send the to
prop used by Link
by giving it to Tab
control. You can send any additional props in the same way. Note that this is documented explicitly for both ButtonBase
and Tab
.
Thanks @josh-l for asking this to be added.
Check this link, I implemented the solution and worked for me
Composition in material UI