Children over render props
Pass structure as children. Keep render props for handing data back.
From vercel-composition-patterns, rule children-over-render-props.
Customize the footer
Apply each change. Compare the code you touch.
renderX propsBad
3 callback slots
last edit ±0 lines0 lines total
renderFooter replaces the defaultchildrenGood
plain JSX, no signatures
last edit ±0 lines0 lines total
add, move or drop a linefunction ComposerFrame({ children }: { children: React.ReactNode }) {
return <form>{children}</form>
}
function ComposerFooter({ children }: { children: React.ReactNode }) {
return <footer className='flex'>{children}</footer>
}
// Usage is flexible
return (
<Composer.Frame>
<CustomHeader />
<Composer.Input />
<Composer.Footer>
<Composer.Formatting />
<Composer.Emojis />
<SubmitButton />
</Composer.Footer>
</Composer.Frame>
)
When the parent owns the data
Scroll both lists. Count the rows each one builds.
children for rowsBad
0 rows built0 ms to mount
{items.map((item) => <Row item={item} />)}renderItemGood
0 rows on screen0 renderItem calls
renderItem={({ item, index }) => …}// Render props work well when you need to pass data back
<List
data={items}
renderItem={({ item, index }) => <Item item={item} index={index} />}
/>
Why it matters, pros and cons
Why it matters
Children read like the UI they build. A render prop earns its place only when the parent hands data back.
Pros
- No callback signatures to learn.
- Reorder or insert by moving one line.
- Defaults stay; you add instead of replace.
Cons
- A list that picks visible rows needs
renderItem. - Children get no per-row data without context.
- A slot with one fixed spot can stay a named prop.