ui icon indicating copy to clipboard operation
ui copied to clipboard

forwardRef broken for radix-ui components

Open remoblaser opened this issue 1 year ago • 9 comments

Installing any components using radix-ui under the hood results in a TypeScript error:

Type 'ForwardRefExoticComponent<LabelProps & RefAttributes<HTMLLabelElement>>' does not satisfy the constraint 'keyof IntrinsicElements | ForwardRefExoticComponent<any> | (new (props: any) => Component<any, {}, any>) | ((props: any, context?: any) => ReactElement<...> | null)'.
  Type 'ForwardRefExoticComponent<LabelProps & RefAttributes<HTMLLabelElement>>' is not assignable to type 'ForwardRefExoticComponent<any>'.
    Type 'ReactNode' is not assignable to type 'ReactElement<any, string | JSXElementConstructor<any>> | null'.
      Type 'undefined' is not assignable to type 'ReactElement<any, string | JSXElementConstructor<any>> | null'.ts(2344)

The component itself is added via CLI:

import * as React from "react";
import * as LabelPrimitive from "@radix-ui/react-label";
import { cva, type VariantProps } from "class-variance-authority";

import { cn } from "@/utils/shadcn";

const labelVariants = cva(
  "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
);  

const Label = React.forwardRef<
  React.ElementRef<typeof LabelPrimitive.Root>,
  React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
    VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => (
  <LabelPrimitive.Root
    ref={ref}
    className={cn(labelVariants(), className)}
    {...props}
  />
));
Label.displayName = LabelPrimitive.Root.displayName;

export { Label };

Tested with:

  • @radix-ui/react-checkbox": "^1.0.4"
  • @radix-ui/react-label": "^2.0.2"

remoblaser avatar Aug 02 '23 21:08 remoblaser

I'm getting same errors in many components, like react-dialog. Any idea on how to fix?

tebuevd avatar Aug 04 '23 00:08 tebuevd

@tebuevd fixed by updating react, node and typescript:

"react": "18.2.0",
"react-dom": "18.2.0",
"typescript": "5.1.6"
"@types/node": "20.4.6",
"@types/react": "18.2.18",
"@types/react-dom": "18.2.7",

remoblaser avatar Aug 04 '23 10:08 remoblaser

I will try as well and circle back

tebuevd avatar Aug 04 '23 15:08 tebuevd

Update: it fixed most of the components, but the command one is still broken:

Type 'ForwardRefExoticComponent<Children & DivProps & { label?: string | undefined; shouldFilter?: boolean | undefined; filter?: ((value: string, search: string) => number) | undefined; value?: string | undefined; onValueChange?: ((value: string) => void) | undefined; loop?: boolean | undefined; } & RefAttributes<...>> & ...' does not satisfy the constraint 'keyof IntrinsicElements | ForwardRefExoticComponent<any> | (new (props: any) => Component<any, {}, any>) | ((props: any, context?: any) => ReactNode)'.
  Type 'ForwardRefExoticComponent<Children & DivProps & { label?: string | undefined; shouldFilter?: boolean | undefined; filter?: ((value: string, search: string) => number) | undefined; value?: string | undefined; onValueChange?: ((value: string) => void) | undefined; loop?: boolean | undefined; } & RefAttributes<...>> & ...' is not assignable to type 'ForwardRefExoticComponent<any>'.
    Type 'React.ReactNode' is not assignable to type 'import("/Users/home/projects/node_modules/.pnpm/@[email protected]/node_modules/@types/react/index").ReactNode'.ts(2344)

tebuevd avatar Aug 04 '23 17:08 tebuevd

@tebuevd any luck?

okhaimie-dev avatar Aug 23 '23 10:08 okhaimie-dev

I think the issue I posted today is the same issue right? https://github.com/shadcn-ui/ui/issues/1459

Any luck finding a solution? As stated in my issue, I already run the latest version of every dependency.

rnnyrk avatar Sep 06 '23 12:09 rnnyrk

@rnnyrk I believe the culprit is the Command component. At least in my codebase that's the only one that's broken. To fix it, I used the any type. I'm sure shadcn will get to it at some point.

const Command = React.forwardRef<typeof CommandPrimitive, any>(
	({ className, ...props }, ref) => (
		<CommandPrimitive
			className={cn(
				"bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
				className,
			)}
			ref={ref}
			{...props}
		/>
	),
);

Do this^ to every components in the command.tsx file.

tebuevd avatar Sep 06 '23 20:09 tebuevd

I think this is still an issue unfortunately.

DaveHellsmith avatar Jan 29 '24 07:01 DaveHellsmith

abstract example in the docs is failing in Typescript because it's missing the definition of the types in forwardRef. That should fix it:

export const DialogContent = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Root>, React.PropsWithChildren<typeof DialogPrimitive.Root>>(
  ({ children, ...props }, forwardedRef) => (
    <DialogPrimitive.Portal>
      <DialogPrimitive.Overlay />
      <DialogPrimitive.Content {...props} ref={forwardedRef}>
        {children}
        <DialogPrimitive.Close aria-label="Close">
          <Cross1Icon />
        </DialogPrimitive.Close>
      </DialogPrimitive.Content>
    </DialogPrimitive.Portal>
  )
);

mauricioribeiro avatar Jan 31 '24 18:01 mauricioribeiro

This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.

shadcn avatar Jun 12 '24 23:06 shadcn

i am having same issue, i am using react 18.2.0

image

not getting any error in ide but getting error when i try to build

KMJ-007 avatar Aug 07 '24 12:08 KMJ-007