Composition
Sometimes you may need to replace one component with another, for example a Button should be a Link.
This is where asChild comes into the picture.
In the code snippet above, the Button component is rendered as a Link component. When this is rendered to the DOM, only one element is rendered.
This happens with the help of Radix's Slot component. 1
Slot merges its props down to the component that sits as a child element. In the case above, Button's props are added to the Link component, and an a tag is rendered.
When you use asChild, you cannot have more than one child element, but you can have as many as you want inside that element.
Why use asChild?
We have previously used an as prop to render as other elements. But when you use this, you don't get type safety or correct types according to the element you've changed to with as.
Slot solves this by adding all props to the child element of the component, thereby ensuring type safety.
All class names, aria attributes, and other props that Button has will be added to the Link component.
This means we can offer good accessibility while you can use other components as you wish.
Event handlers
If a prop starts with on (e.g., onClick), it is considered an event handler.
When Slot merges props, it will create a new function that calls all event handlers defined on both Button and Link. The function on Link will be called first.
This means that if you stop an event on your component, the event on the Slot component will not be called.
If one of the event handlers depends on event.defaultPrevented, you need to make sure the order is correct. 2
Use your own components
Several components in Designsystemet support asChild with standard elements. If you change this, you must ensure that accessibility is maintained. It's rare that you need to change the underlying element, but it's more realistic that you'll want to use your own component.
If you want to use your own component, you need to make sure to spread all props and support ref. 3
Your components will then look like this:
Several Design System components support asChild.
References
- [1] Radix Slot
- [2] Radix Slot Event handlers
- [3] Radix Composition