-
-
Save marty-mcgee/84a5ec09c0d097e1ad86764ce8405529 to your computer and use it in GitHub Desktop.
Next.js Link + Material UI Link/Button components bundled with forwardRef
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Plain JS version + prop-types | |
// Thanks to @IvanAdmaers | |
import PropTypes from 'prop-types'; | |
import { forwardRef } from 'react'; | |
import NextLink from 'next/link'; | |
import { Link as MuiLink } from '@material-ui/core'; | |
const Link = forwardRef(({ href, as, prefetch, ...props }, ref) => { | |
return ( | |
<NextLink href={href} as={as} prefetch={prefetch} passHref> | |
<MuiLink ref={ref} {...props} /> | |
</NextLink> | |
); | |
}); | |
Link.displayName = 'Link'; | |
Link.defaultProps = { | |
href: '#', | |
prefetch: false, | |
}; | |
Link.propTypes = { | |
href: PropTypes.string, | |
as: PropTypes.string, | |
prefetch: PropTypes.bool, | |
}; | |
export default Link; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// MaterialUI v4 | |
import React, { forwardRef, Ref } from 'react' | |
import Link, { LinkProps } from 'next/link' | |
import { Link as MuiLink, LinkProps as MuiLinkProps } from '@material-ui/core' | |
type LinkRef = HTMLAnchorElement | |
type NextLinkProps = Omit<MuiLinkProps, 'href' | 'classes'> & | |
Pick<LinkProps, 'href' | 'as' | 'prefetch'> | |
const NextLink = ({ href, as, prefetch, ...props }: LinkProps, ref: Ref<LinkRef>) => ( | |
<Link href={href} as={as} prefetch={prefetch} passHref> | |
<MuiLink ref={ref} {...props} /> | |
</Link> | |
) | |
export default forwardRef<LinkRef, NextLinkProps>(NextLink) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// MaterialUI v5 | |
// Thanks to @bryantobing12 | |
import React from "react"; | |
import { Link as LinkMUI, LinkProps as LinkMUIProps } from "@mui/material"; | |
import NextLink, { LinkProps as NextLinkProps } from "next/link"; | |
export type LinkProps = Omit<LinkMUIProps, "href" | "classes"> & | |
Pick<NextLinkProps, "href" | "as" | "prefetch">; | |
export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>( | |
({ href, as, prefetch, ...props }, ref) => ( | |
<NextLink href={href} as={as} prefetch={prefetch} passHref> | |
<LinkMUI ref={ref} {...props} /> | |
</NextLink> | |
) | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @source https://github.com/mui/material-ui/tree/master/examples/nextjs-with-typescript | |
// Updated in this gist by @alecriarstudio | |
import * as React from 'react'; | |
import clsx from 'clsx'; | |
import { useRouter } from 'next/router'; | |
import NextLink, { LinkProps as NextLinkProps } from 'next/link'; | |
import MuiLink, { LinkProps as MuiLinkProps } from '@mui/material/Link'; | |
import { styled } from '@mui/material/styles'; | |
// Add support for the sx prop for consistency with the other branches. | |
const Anchor = styled('a')({}); | |
type NextLinkComposedProps = { | |
to: NextLinkProps["href"]; | |
linkAs?: NextLinkProps["as"]; | |
} & Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "href"> & | |
Omit<NextLinkProps, "href" | "as">; | |
export const NextLinkComposed = React.forwardRef<HTMLAnchorElement, NextLinkComposedProps>( | |
function NextLinkComposed(props, ref) { | |
const { to, linkAs, replace, scroll, shallow, prefetch, locale, ...other } = props; | |
return ( | |
<NextLink | |
href={to} | |
prefetch={prefetch} | |
as={linkAs} | |
replace={replace} | |
scroll={scroll} | |
shallow={shallow} | |
passHref | |
locale={locale} | |
> | |
<Anchor ref={ref} {...other} /> | |
</NextLink> | |
); | |
}, | |
); | |
export type LinkProps = { | |
activeClassName?: string; | |
as?: NextLinkProps['as']; | |
href: NextLinkProps['href']; | |
linkAs?: NextLinkProps['as']; // Useful when the as prop is shallow by styled(). | |
noLinkStyle?: boolean; | |
} & Omit<NextLinkComposedProps, 'to' | 'linkAs' | 'href'> & | |
Omit<MuiLinkProps, 'href'>; | |
// A styled version of the Next.js Link component: | |
// https://nextjs.org/docs/api-reference/next/link | |
const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(function Link(props, ref) { | |
const { | |
activeClassName = 'active', | |
as, | |
className: classNameProps, | |
href, | |
linkAs: linkAsProp, | |
locale, | |
noLinkStyle, | |
prefetch, | |
replace, | |
role, // Link don't have roles. | |
scroll, | |
shallow, | |
...other | |
} = props; | |
const router = useRouter(); | |
const pathname = typeof href === 'string' ? href : href.pathname; | |
const className = clsx(classNameProps, { | |
[activeClassName]: router.pathname === pathname && activeClassName, | |
}); | |
const isExternal = | |
typeof href === 'string' && (href.indexOf('http') === 0 || href.indexOf('mailto:') === 0); | |
if (isExternal) { | |
if (noLinkStyle) { | |
return <Anchor className={className} href={href} ref={ref} {...other} />; | |
} | |
return <MuiLink className={className} href={href} ref={ref} {...other} />; | |
} | |
const linkAs = linkAsProp || as; | |
const nextjsProps = { to: href, linkAs, replace, scroll, shallow, prefetch, locale }; | |
if (noLinkStyle) { | |
return <NextLinkComposed className={className} ref={ref} {...nextjsProps} {...other} />; | |
} | |
return ( | |
<MuiLink | |
component={NextLinkComposed} | |
className={className} | |
ref={ref} | |
{...nextjsProps} | |
{...other} | |
/> | |
); | |
}); | |
export default Link; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment