Deprecate `render` prop and use `asChild` with `children` instead
- Dominant language
- TypeScript
- Stars
- 10.9k
- Forks
- 543
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 101
Description
# Feature request
**Please upvote if you want this implemented ๐๐๐**
## Deprecate `render` prop and use `asChild` with `children` instead
Instead of using: `span render prop} />` change API to be able to use `asChild` prop: `span render prop`
## Examples in other libraries
https://www.radix-ui.com/primitives/docs/guides/composition
Also tanstack form uses children as render prop: https://tanstack.com/form/latest/docs/framework/react/guides/basic-concepts#field
## Motivation
I do not really understand why Base UI team chose `render` prop instead of using `asChild` combined with `children`. `render` prop is **worse** in all cases than `asChild` prop:
Disadvantages of `render` prop:
1. No type safety, contradictory state, this is valid tsx code:
```tsx
Will this be rendered?}>
```
2. More cluttered jsx, the render prop make jsx shift more to the right with formatting.
3. More cognitive load, with `asChild` prop and `children` it is more natural read and understand jsx.
Advantages of `asChild`
1. Easier migration for users with radix primitives projects, less code to migrate.
2. Stricter, more type safe API and UX, children can be also function:
Instead of this:
```tsx
click me}>
Oppps, I am here
```
Use this:
```tsx
{(htmlProps, buttonState) => looks better}
```
3. Also the `children` prop can be used same as `render` prop when combined with `asChild`:
```tsx
looks better}
/>
```
Or:
```tsx
looks better} />
```
I am also curious why the `render` prop was chosen instead of `asChild`. It makes migrating radix projects more difficult without clear benefits which I can see... Functionally these approaches are both basically the same so why not use the `asChild` which preserves compatibility with radix and is more natural to use together with `children`
### **Edit** February 6:
After discussion my proposed solution is this:
Use children as jsx with `asChild` prop:
```tsx
click me
// or with prop
click me} />
```
And functional approach just use function without `asChild` prop:
```tsx
{(htmlProps, buttonState) => looks better}
// or with prop
hello} />
```
So children will behave the same as render prop when it is a function or when `asChild` attrubute is provided.
Contributor guide
Assessment
This issue has not been assessed yet.