Fluentui: React Router support discussion

Created on 21 Mar 2017  路  17Comments  路  Source: microsoft/fluentui

I want to discuss issue with React Router support. In CommandBar/ContextualMenu/etc. there is href prop, but it's doesn't work with React Router. Now I'm handling onClick event and then call router push method. But it's not a good solution, because it's not a link, I can't open this in new tab/copy link/etc. in browser.

What is the best way to implement this?

My vision is:

onHrefRender?: (item: React.ReactNode, anchorProps: any) => React.ReactNode;

and using:

import { Link } from 'react-router';
//...
{
    key: 'homepage',
    name: 'Home',
    onHrefRender: (item, aProps) => <Link { ...aProps } to="/index" >{ item }</Link>
};
Feature

Most helpful comment

I know this is a long time coming (especially for such a small change). But this codepen using React Router will work once the new release is pushed out tonight.

There are a few styling differences, but nothing too horrible. I'll try to update once the code is released.

https://codepen.io/micahgodbolt/pen/EOVXGQ?editors=1010

All 17 comments

I don't totally understand why they made the Link component for react-router, which generates DOM, rather than a utility to return an href or onClick handler that they can interpret. Is there a method in react-router to generate an href for a normal link? I can't find one in their documentation.

e.g. this would make sense to me.

import { routeHref, routeClick } from 'react-router';

<IconButton href={ routeHref('/index') } />
<NavItem onClick={ routeClick('/index') } />

In this case the router can work as expected, but you can use whatever presentation you'd like.

We have logic in the BaseButton to use an anchor if there is an href, otherwise a button. That way anchors have the consistent anchor behaviors, like ctrl/cmd-clicking and status bar on hover, while non-href based things don't. But you can have them look consistent.

This is what we want to standardize on for all clicky components, so the Link, *Button, ContextualMenuItem, NavItem, etc are just variants of the base button. React-router fights against this because it wants to own the DOM element too, which adds confusion regarding the right way to handle this.

One option is to have a mode for all buttons that is "presentation only" which renders the presentation of the button without the A or the BUTTON wrapper... Then you can wrap that in a Link:

<Link to={...}><IconButton presentationOnly /></Link>

But I'm not sure about the side-effects. For example, when we add split button support, which is a DIV which wraps 2 buttons, this doesn't work.

For container components like ContextualMenu and Nav, no matter what, the child render methods should always be override-able via onRender* IRenderFunction overrides, allowing you to support something like this.

Is there a method in react-router to generate an href for a normal link?
There is createHref, but it's do this:

console.log(this.context.router.createHref('/home'));  // /home

Generate only path, and doesn't handle click on a or something like this.

I need this only for ContextualMenu/CommandBar, Buttons I always cover via Link.
So we can add onHrefRender for ContextualMenu or add rendered Item (React.Node) to onRender via param, to allow me cover Item via Link.

@dzearing I think afterRender* for ContextualMenu will resolve this.

afterRender?: (renderedItem: React.ReactNode, item: any) => React.ReactNode;

If this ok, I'll create PR.

@fantua @dzearing I think we should change the ContextualMenuItem onRender prop to follow the the IRenderFunction convention of passing in the defaultRender function.

@cschleiden looks like that is exactly what I need!

@fantua @cschleiden I'd love all onRender* methods to follow the IRenderFunction convention and would gladly welcome that change.

That said; I don't think it will improve the Link usage. Link will still want to render the A tag, so rendering a nested BUTTON or A inside of an A doesn't work correctly in the browser.

But, I could be wrong. So If you'd like to convert it to onRenderItem: IRenderFunction<IButtonProps> I think that would be awesome!

I can't convert ContextualMenuItem onRender prop to IRenderFunction. Because IRenderFunction accept only 1 param which always is item, but ContextualMenu render methods need more params.

private _renderNormalItem(item: IContextualMenuItem, index: number, hasCheckmarks: boolean, hasIcons: boolean): React.ReactNode {
    if (item.onRender) {
      return [item.onRender(item)];
    }
    if (item.href) {
      return this._renderAnchorMenuItem(item, index, hasCheckmarks, hasIcons);
    }
    return this._renderButtonItem(item, index, hasCheckmarks, hasIcons);
  }

How override this to IRenderFunction?

@dzearing @cschleiden how to solve this?

Any thoughts on this issue? It's quite something fundamental. I'd love to pitch in if we know the direction were heading with this.

@fantua You could have something like IContextualMenuItemRenderProps that groups all of these props

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions to Fabric React!

So what is the suggested way to use fabric react nav and react-router together?

This issue has been automatically marked as stale because it has not activity for 30 days. It will be closed if no further activity occurs within 14 days of this comment. Thank you for your contributions to Fabric React!
Why am I receiving this notification?

Bumping so this doesn't get closed.

I know this is a long time coming (especially for such a small change). But this codepen using React Router will work once the new release is pushed out tonight.

There are a few styling differences, but nothing too horrible. I'll try to update once the code is released.

https://codepen.io/micahgodbolt/pen/EOVXGQ?editors=1010

:tada:This issue was addressed in #7006, which has now been successfully released as [email protected].:tada:

Handy Links:

Was this page helpful?
0 / 5 - 0 ratings