Capítulo 50 de 51
A specialized Object.assign-like utility for combining prop objects (internal component props + consumer-supplied props) that specifically knows how to combine event handlers (all invoked, rightmost-first), className (concatenated), and style (shallow-merged) — the tool needed inside every function-form render prop, since props there are not auto-merged.
className/style/event handlers/ref, the rightmost argument wins — plain Object.assign semantics.ref is never merged: only the rightmost ref survives — use useRender's own ref array option (ch007/ch010) when multiple refs need to coexist, not mergeProps.className: concatenated right-to-left (rightmost class appears first in the resulting string) — mergeProps({className:'a'}, {className:'b'}) → 'b a'.style: objects shallow-merged, rightmost key wins on conflict.event.preventBaseUIHandler() to stop earlier (leftward) handlers — and, per ch008, stop Base UI's own internal handling too. This mechanism does not exist for non-synthetic/custom events — all handlers there always run, unconditionally.(mergedPropsSoFar) => propsObject instead of a plain object — receives the left-to-right accumulated merge so far. Its return value replaces the accumulation entirely for that step — if it needs to preserve a previous handler, it must call it manually (props.onClick?.(event) inside the new handler) since automatic chaining does not apply across a function argument's boundary.mergeProps (≤5 args) vs. mergePropsN (array, unlimited): prefer mergeProps for 5 or fewer prop sets — mergePropsN is measurably slower due to array handling, only reach for it above that count.mergeProps({ id: 'a', dir: 'ltr' }, { id: 'b' }); // { id: 'b', dir: 'ltr' }
mergeProps({ className: 'a' }, { className: 'b' }); // className: 'b a'
mergeProps({ onClick: a }, { onClick: b }); // b runs, then a
/* Using mergeProps inside a render callback (the primary real-world use case) */
<Component render={(props, state) => (
<button {...mergeProps<'button'>(props, { className: styles.Button })} />
)} />
/* Locking a Toggle's interaction via preventBaseUIHandler */
const getToggleProps = (props) => mergeProps<'button'>(props, {
onClick(event) {
if (locked) event.preventBaseUIHandler();
},
});
<Toggle render={(props, state) => <button {...getToggleProps(props)} />} />
preventBaseUIHandler() lets a wrapping handler veto both earlier user handlers and the component's own internal click logic (e.g. actually toggling) in one call — the standard way to build a "locked" interactive control on top of a Base UI primitive.mergeProps (not manual spreading) inside a function-form render prop — plain {...props, className: 'x'} silently drops the component's own className/event handlers instead of combining them.event.preventBaseUIHandler() specifically when you need to conditionally suppress a Base UI component's own internal behavior (e.g. a lockable toggle) — it has no effect on non-synthetic events, so verify the event type first.mergeProps over mergePropsN unless merging more than 5 prop sets — the array-based variant is explicitly documented as slower.render prop this utility is built for.preventBaseUIHandler() vs. eventDetails.cancel() — two different interception mechanisms for two different layers (raw DOM event handler vs. Base UI's own change-event system).mergeProps internally to combine a custom component's default props with consumer-supplied ones.