0

So my guess is that if custom component doesn't accept children and has DOM element like button, then we should spread props and pass ref to it.

But if custom component gets children instead and has multiple radix element nested, I don't know where to spread props and pass our ref. Onto the one that is direct parent of {children} or the one that is on top level? Or how we decide it?

I have 3 sample components given. Please explain for each of them where props and refs should go and why. Also since I am not sure which element gets props and refs, I was not able to give proper TS types.


// sample 1
const ToolbarButtonWithTooltip = React.forwardRef<any, any>(
    ({ children, tooltipContent, ...props }, forwardedRef) => {
        return (
            <Toolbar.Button asChild>
                <TooltipProvider tooltipContent={tooltipContent}>
                    <button
                        {...props}
                        ref={forwardedRef}
                        className="cursor-pointer rounded bg-blue-500 text-slate-50"
                    >
                        {children}
                    </button>
                </TooltipProvider>
            </Toolbar.Button>
        );
    }
);

// sample 2
const TooltipProvider = forwardRef<any, any>(({ tooltipContent, children, ...props }, forwardedRef) => {
    return (
        <Tooltip.Provider delayDuration={100}>
            <Tooltip.Root>
                <Tooltip.Trigger asChild>
                    { children }
                </Tooltip.Trigger>
                <Tooltip.Portal>
                    <Tooltip.Content className="rounded bg-slate-900 p-1 text-slate-50">
                        {tooltipContent}
                        <Tooltip.Arrow className="fill-slate-900" />
                    </Tooltip.Content>
                </Tooltip.Portal>
            </Tooltip.Root>
        </Tooltip.Provider>
    );
});

// sample 3
const SelectViewPort = forwardRef<any, any>(({ children, ...props }, forwardedRef) => {
    return (
        <Select.Portal>
            <Select.Content>
                <Select.Viewport
                    className="rounded bg-slate-900 text-slate-50"
                >
                    {children}
                </Select.Viewport>
            </Select.Content>
        </Select.Portal>
    );
});```


(I checked shadcn ui library to see where he passes props and refs, but it didn't help me understanding it)
Terlan
  • 13
  • 3
  • It depends. What props exactly do you want to spread? In the first snippet you use three components: `Toolbar.Button`, `TooltipProvider` and `button`, each one has its own props. Choose which props you want to be able to customize when using your `ToolbarButtonWithTooltip` and pass every prop to the component that accepts it. If you need only a subset of props, then specify the exact subset and don't use spread at all, just pass one by one. If you want p.e. all props from `button` and some from `Button` and `Provider`, pass the latter ones one by one and the rest to `button` using spread – Alex Chashin Jul 08 '23 at 08:52
  • Well it's not about my props. Radix UI library recommends to spread props and forward refs always if you are using custom component, because library will pass its own props to our component. Also react gives warnings if we dont wrap component inside of forwardRef. So I am not sure where to spread them. – Terlan Jul 08 '23 at 09:03
  • Are you talking about [this](https://www.radix-ui.com/docs/primitives/guides/composition#your-component-must-spread-props)? It says that if you specify `asChild` on component `A` and the component `B` that you use as a child of `A` is a custom react component (not an html element), then this component `B` must spread all of its props and forward ref to whatever it renders (because radix will pass some additional props to `B`, like maybe `style`). So it's `B` that must spread its props, not the component where `A` is rendered. In your case `B` is an html button, so it doesn't need any treatment – Alex Chashin Jul 08 '23 at 12:54
  • If you are talking about something different, please attach a link to documentation where else they recommend forwarding props and refs. – Alex Chashin Jul 08 '23 at 12:54

0 Answers0