1.8 KiB
1.8 KiB
title, impact, impactDescription, tags
| title | impact | impactDescription | tags |
|---|---|---|---|
| Prefer Composing Children Over Render Props | MEDIUM | cleaner composition, better readability | composition, children, render-props |
Prefer Children Over Render Props
Use children for composition instead of renderX props. Children are more
readable, compose naturally, and don't require understanding callback
signatures.
Incorrect (render props):
function Composer({
renderHeader,
renderFooter,
renderActions,
}: {
renderHeader?: () => React.ReactNode;
renderFooter?: () => React.ReactNode;
renderActions?: () => React.ReactNode;
}) {
return (
<form>
{renderHeader?.()}
<Input />
{renderFooter ? renderFooter() : <DefaultFooter />}
{renderActions?.()}
</form>
);
}
// Usage is awkward and inflexible
return (
<Composer
renderHeader={() => <CustomHeader />}
renderFooter={() => (
<>
<Formatting />
<Emojis />
</>
)}
renderActions={() => <SubmitButton />}
/>
);
Correct (compound components with children):
function 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 render props are appropriate:
// Render props work well when you need to pass data back
<List data={items} renderItem={({ item, index }) => <Item item={item} index={index} />} />
Use render props when the parent needs to provide data or state to the child. Use children when composing static structure.