I'm stuck trying to get the ui-fabric Nav component working with react-router-dom v4+. My solution "works", but the whole page is rerendered instead of just the NavSelection component. After some research i realize i need to do a e.preventDefault() somewhere, but i can't figure out where to add it.
Main Page:
export const Home = () => {
return (
<div className="ms-Grid-row">
<div className="ms-Grid-col ms-u-sm6 ms-u-md4 ms-u-lg2">
<Navbar />
</div>
<div className="ms-Grid-col ms-u-sm6 ms-u-md8 ms-u-lg10">
<NavSelection />
</div>
</div>
);
}
Navbar:
const navGroups = [
{
links: [
{ name: 'Name1', url: '/Name1', key: '#Name1' },
{ name: 'Name2', url: '/Name2', key: '#Name2' }
]
}
];
export class Navbar extends React.Component<any, any> {
constructor(props: INavProps) {
super(props);
this.state = {
selectedNavKey: '#Name1'
};
}
public componentDidMount() {
window.addEventListener('hashchange', (e) => {
this.setState({ selectedNavKey: document.location.hash || '#' });
});
}
public render(): JSX.Element {
const { selectedNavKey } = this.state;
return (
<Nav
selectedKey={selectedNavKey}
groups={navGroups}
/>
);
}
}
NavSelection:
export const NavSelection = () => {
return (
<div>
<Route path="/Name1" component={Component1} />
<Route path="/Name2" component={Component2} />
</div>
);
}
Any help is greatly appreciated
Edit: I've tried to put it inside componentDidMount like this:
public componentDidMount() {
window.addEventListener('hashchange', (e) => {
e.preventDefault();
this.setState({ selectedNavKey: document.location.hash || '#' });
});
}
That does not work.
I'm guessing you are using Microsoft's https://developer.microsoft.com/en-us/fabric#/components/nav#Variants
In that case you need to specify the callback on the nav item. Usually it's anti-pattern to use things like window.addEventListener
in react.
This would look something like.
export class Navbar extends React.Component<any, any> {
constructor(props: INavProps) {
super(props);
this.state = {
selectedNavKey: '#Name1'
};
}
public handleNavClick(event, { key, url }) {
// You also need to manually update the router something like
history.push(url);
this.setState({ selectedNavKey: key });
}
public render(): JSX.Element {
const { selectedNavKey } = this.state;
return (
<Nav
selectedKey={selectedNavKey}
groups={{
links: [
{ name: 'Name1', url: '/Name1', key: '#Name1', onClick: this.handleNavClick },
{ name: 'Name2', url: '/Name2', key: '#Name2', onClick: this.handleNavClick }
]
}}
/>
);
}
}