gatsby: [TS] Link is incompatible with React.forwardRef due to ref type mismatch
Preliminary Checks
- This issue is not a duplicate. Before opening a new issue, please search existing issues: https://github.com/gatsbyjs/gatsby/issues
- This issue is not a question, feature request, RFC, or anything other than a bug report directly related to Gatsby. Please post those things in GitHub Discussions: https://github.com/gatsbyjs/gatsby/discussions
Description
In a TypeScript environment, Gatsby’ Link component is not compatible with React.forwardRef due to a ref type mismatch.
Reproduction Link
Steps to Reproduce
Run this code:
import type { GatsbyLinkProps } from "gatsby";
import { Link } from "gatsby";
import React, { forwardRef } from "react";
export type MyLinkProps = GatsbyLinkProps<unknown>;
export const MyLink = forwardRef<HTMLAnchorElement, MyLinkProps>(
function MyLink(props, ref) {
return <Link {...props} ref={ref} activeClassName="active" />;
}
);
Expected Result
Works normally.
Actual Result
TypeScript complains about a type mismatch on ref={ref}:
No overload matches this call.
Overload 1 of 2, '(props: GatsbyLinkProps<unknown> | Readonly<GatsbyLinkProps<unknown>>): GatsbyLink<unknown>', gave the following error.
Type 'ForwardedRef<HTMLAnchorElement>' is not assignable to type '((string | ((instance: GatsbyLink<unknown> | null) => void) | RefObject<GatsbyLink<unknown>>) & (string | ((instance: HTMLAnchorElement | null) => void) | RefObject<...>)) | null | undefined'.
Type '(instance: HTMLAnchorElement | null) => void' is not assignable to type '((string | ((instance: GatsbyLink<unknown> | null) => void) | RefObject<GatsbyLink<unknown>>) & (string | ((instance: HTMLAnchorElement | null) => void) | RefObject<...>)) | null | undefined'.
Type '(instance: HTMLAnchorElement | null) => void' is not assignable to type 'string & ((instance: HTMLAnchorElement | null) => void)'.
Type '(instance: HTMLAnchorElement | null) => void' is not assignable to type 'string'.
Overload 2 of 2, '(props: GatsbyLinkProps<unknown>, context: any): GatsbyLink<unknown>', gave the following error.
Type 'ForwardedRef<HTMLAnchorElement>' is not assignable to type '((string | ((instance: GatsbyLink<unknown> | null) => void) | RefObject<GatsbyLink<unknown>>) & (string | ((instance: HTMLAnchorElement | null) => void) | RefObject<...>)) | null | undefined'.
My workaround to date depends on stripping ref from GatsbyLinkProps, and then passing my forwarded ref to deprecated prop innerRef, like so:
import type { GatsbyLinkProps } from "gatsby";
import { Link } from "gatsby";
import React, { forwardRef } from "react";
export type MyLinkProps = Omit<GatsbyLinkProps<unknown>, "ref">;
export const MyLink = forwardRef<HTMLAnchorElement, MyLinkProps>(
function MyLink(props, ref) {
return <Link {...props} innerRef={ref} activeClassName="active" />;
}
);
But this wasn’t much fun to figure out, nor should it be necessary. Gatsby’s Link should be directly compatible with forwardRef out of the box.
Among other things, this would make it possible to pass component={Link} when using MUI. MUI is a (the?) leading React front end framework, and improving compatibility here would be a big plus.
Environment
Gatsby 4.4.0.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 9
- Comments: 23 (7 by maintainers)
Not stale.
Still not stale!
Hopefully this can be addressed as part of PR #22027, though there hasn’t been much progress there.