mui / mui/base-ui

Deprecate `render` prop and use `asChild` with `children` instead

Open
#3,983 8 comments 23 reactions 0 assignees View on GitHub
breaking change discussion scope: all components
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?}>

Or maybe this? Who knows...

```

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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.