-
-
Save zackdotcomputer/d7af9901e7db87364aad7fbfadb5c99b to your computer and use it in GitHub Desktop.
// Created by Zack Sheppard (@zackdotcomputer) on 1/19/2021 | |
// Freely available under MIT License | |
// Workaround for https://github.com/vercel/next.js/issues/5533 | |
import Link, { LinkProps } from "next/link"; | |
import { AnchorHTMLAttributes, PropsWithChildren } from "react"; | |
type PropTypes = LinkProps & Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "href">; | |
/// A unified component for the next/link <Link> and a standard <a> anchor. | |
/// Will lift href and all other props from Link up to the Link. | |
/// Will automatically make an <a> tag containing the children and pass it remaining props. | |
const LinkTo = ({ | |
children, | |
href, | |
as, | |
replace, | |
scroll, | |
shallow, | |
prefetch, | |
locale, | |
...anchorProps | |
}: PropsWithChildren<PropTypes>) => { | |
return ( | |
// These props are lifted up to the `Link` element. All others are passed to the `<a>` | |
<Link {...{ href, as, replace, scroll, shallow, prefetch, locale }}> | |
{/* eslint-disable-next-line react/jsx-props-no-spreading */} | |
<a {...anchorProps}>{children}</a> | |
</Link> | |
); | |
}; | |
export default LinkTo; |
Hi there,
with typescript in strict mode, the native Link component is throwing an error: Type 'string | undefined' is not assignable to type 'Url'.
I thinkered a bit and came to the following changes:
import Link, { LinkProps } from "next/link";
import { AnchorHTMLAttributes, PropsWithChildren } from "react";
type PropTypes = LinkProps & AnchorHTMLAttributes<HTMLAnchorElement>;
/// A unified component for the next/link <Link> and a standard <a> anchor.
/// Will lift href and all other props from Link up to the Link.
/// Will automatically make an <a> tag containing the children and pass it remaining props.
const LinkTo = ({
children,
href,
as,
replace,
scroll,
shallow,
prefetch,
locale,
...anchorProps
}: PropsWithChildren<PropTypes>) => {
return (
// These props are lifted up to the `Link` element. All others are passed to the `<a>`
<Link {...{ href, as, replace, scroll, shallow, prefetch, locale }}>
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<a {...anchorProps}>{children}</a>
</Link>
);
};
export default LinkTo;
What do you think about this solution? After a few tests, everything seems to work fine, the href is passed correctly to the Link-Component and is rendered into the dom (in dev and build). The LinkTo-Component even typechecks for a href, which your orginal solution does not (at least for me).
@Jak-Ch-ll looks good - I am running this with a subset of strict
rather than the whole shebang so I wasn't seeing the error you got. I like your solution of just pulling in the Props from Next rather than trying to clone them, the only change I'm going to make is that I think we should Omit
the href
key from AnchorHTMLAttributes
in our Props union so that we don't wind up confusing the type there. I'll update the gist with that now.
@zackdotocomputer ah cool, learned something new. I didn't know about Omit
and that's definitly a good idea!
@adriankwiat What versions of Typescript and Next are you using? And what does your tsconfig
look like? That is strange but I'm guessing it is a strictness check in typescript that is complaining that TECHNICALLY as?: Url
and as: Url | undefined
are different (though functionally they are basically the same).
I see that my VSCode uses dev version of typescript 4.4.0. Changing back to stable 4.3.2 resolved problem. I didn't think about that before
Oof good to know that this might break with 4.4 though
Hi made a similar solution but instead of AnchorHTMLAttributes
I used HTMLAttributes
. Just wanted to thank you for the solution :D
Note: this is written in Typescript 4 for Next 10. ymmv if not on those versions.