Andrew's Digital Garden

Radix's asChild prop, and other styling APIs

Radix uses an asChild prop, which is a similar vein to styled-components' as prop. It's intended to be a better API to encompass the functionality of as.

Allows you to attach a components functionality to a different DOM element. Essentially the parent calls cloneElement(children) with any relevant props. This gives you more control of the child element while retaining the polymorphism. For example, you can pass explicit props to the child element, unlike as.

[[20221017052110-react-element-vs-component]]

<Dialog.Root> <Dialog.Trigger asChild> <Button foo="bar">Open dialog</Button> </Dialog.Trigger> <Dialog.Content>...</Dialog.Content> </Dialog.Root>

Some implementations of as get around this by passing through any props to the parent back to the child component. This brings up new issues, especially around prop naming clashes, or re-defining props on the parent.

Also note that polymorphic React components have their own problems, including poor [[ts]] performance.

Both as and asChild require an intermediate component, which may or may not be a big issue. It's important that this intermediate component spreads the props it receives from the parent. In the above example, Button internally should spread the props received from Dialog.Trigger. Note that often the asChild element is a native HTML element, which circumvents this problem.

tl;dr asChild > as


A [[20221205104221-render-props-pattern]] API also exists in this space, which reakit also offers. This gives you the most customisation by allowing the user to use props as needed. For example, you can inspect the props to apply a conditional class, or pass the props to a different prop on the child component.

<MenuItem> {(props) => { const className = "data-active-item" in props ? "bg-blue" : ""; return <div {...props} className={className} />; }} </MenuItem>

Optionally, the implementation could merge any props passed to the parent component. Achieving type safety here may be difficult.

All in all, render props and as/asChild solve similar but different problems.

https://www.radix-ui.com/docs/primitives/guides/composition https://github.com/ariakit/ariakit/issues/1245 https://www.radix-ui.com/docs/primitives/guides/composition https://twitter.com/diegohaz/status/1669519776345911297

[[designsystem]] [[designsystemapi]] [[react]] [[reactapi]] [[styledcomponents]]

Radix's asChild prop, and other styling APIs