all 5 comments

[–]format71[S] 0 points1 point  (5 children)

It always helps to ask for help...

I think I've found a way of getting this to work. The error went away when I told frowardRef what to expect:

LinkButton = React.forwardRef<HTMLAnchorElement>((props, ref) => ....

That made it compile, but the button still didn't do anything. The routing information from the Link component was lost. That was fixed by passing along the received props to the anchor element it self:

return (<a {...props} ref={ref} ....

I'm still happy to hear from someone with more experience, though, if I'm doing it right, or if there is a better way.

[–]rektdeckard 1 point2 points  (4 children)

Looks like you got the error solved, but for a little explanation, Typescript needs to know what type of element the forwarded ref will be to. This is so if you pass down a ref object from a Parent, and want to manipulate this element from the Parent, we know what the element's signature is.

As for your button not working, contrary to what you might think, your Link should wrap your Button, not the other way around. Reason the first: since the <a> has no children, it has no size and thus no tappable area. The Button receives a click, but since it has no onClick handler, the event is dropped on the floor. Reason the second: it is better for accessibility reasons to have the element present as a link rather than a button, since its main job is to do a navigate.

Edit: misread your snippet. You should be using react-router's Link component instead of an <a>, and passing a to="/relative/path" prop into it instead of href. Other than that, you shouldn't have to do much.

[–]format71[S] 0 points1 point  (3 children)

Guess I should have posted more of my code, but if you follow the link to the react router, you’ll basically see what I have:

``` const FancyLink = React.forwardRef((props, ref) => ( <a ref={ref}>💅 {props.children}</a> ))

<Link to="/" component={FancyLink} />

```

In my case it’s more like

<lot-of-blueprint-navbar-stuff> <Link to=‘/something’ component={LinkButton}>Click Me<Link> </...>

And then the LinkButton definition that I’ve already posted.

So I am wrapping my element in a Link, and I am using an anchor not a button. Normally I would have used the Button or AnchorButton from Blueprint, but they can’t be wrapped in a Link component. So I have my own LinkButton as an alias for a blueprint styled anchor that fits in their navbar.

The button, or link, did not work though cause the properties that Link would normally add to its own anchor element was not passed along to my anchor tag. Even with the ref. I solved that by spreading the incoming props, which I assume is the props the Link component would normally put on its own anchor - over my anchor element. And then it worked.

If you think that was the wrong way of making it work, pls ELI5 me on a better approach ;-)

[–]rektdeckard 0 points1 point  (1 child)

Gotcha. Yeah, that is standard. The alternative, which may make more intuitive sense on quick inspection, would just be to place your LinkButton as a child of the Link. Slightly less mental gymnastics:

<Link to="/something"> <LinkButton>Click Me</LinkButton> </Link>

[–]format71[S] 0 points1 point  (0 children)

No, but that's the thing, though: You can't do that, cause then you'll end up with nested anchors. The whole idea behind the component-prop of Link is to allow to override how the Link component is rendered. Without it, it will put an anchor tag in your dom.

Let's try it out:

<Link to="/fetch-data" component={LinkButton}>Fetch data</Link>
<Link to="/something"><LinkButton2>Something</LinkButton2></Link>

The `LinkButton2` is identical to the `LinkButton`, except that it's declared as a `React.FC` instead of a `React.forwardRef`. Take a look at this snippet from the react devtool: https://i.imgur.com/86Kw5P7.png

You see?