Caveats
Slot Content Keys
When useSlot
parses children
, it flattens the arrays. This allows it to
correctly identify content for slots. For this reason, keys must be unique
within the slot content, even if they are part of different arrays.
function MyComponent({ children }) {
const { slot } = useSlot(children);
return <slot.foo />;
}
// ❌ Incorrect: Duplicate keys 1 and 2
<MyComponent>
{[
<div key={1} slot-name="foo">First node</div>,
<template.foo key={2}>Second second</template.foo>
]}
{[
<span key={1} slot-name="foo">Third node</span>
]}
<span key={2} slot-name="foo">Fourth node</span>
<span slot-name="foo">Fifth node</span>
<span slot-name="foo">Sixth node</span>
</MyComponent>
// ✅ Correct: Keys are different.
<MyComponent>
{[
<div key={1} slot-name="foo">First node</div>,
<template.foo key={2}>Second second</template.foo>
]}
{[
<span key={3} slot-name="foo">Third node</span>
]}
<span key={4} slot-name="foo">Fourth node</span>
<span slot-name="foo">Fifth node</span>
<span slot-name="foo">Sixth node</span>
</MyComponent>
Template as Custom Component Footgun
When you specify a custom component with the template element's as
prop, you
must exercise caution. This is because the children
you specify for the
template element won't be the same children
that will be passed to the as
element. react-slots
is likely to modify the children
in a way that's
significantly different from what you might expect. This is especially true when
OverrideNode
is used within the slot. For this reason, the as
element's
children
must be of type ReactNode
and should only be used within the as
element for the purpose of rendering.
function MyComponent({ children }: { children: string }) {
performSideEffect(children);
return <div>{children}</div>;
}
// ❌ Not Allowed: MyComponent expects a string to perform a side effect with.
// The provided node will likely not be a string.
<template.foo as={MyComponent}>Content</template.foo>;
function MySecondComponent({ children }: { children: React.ReactNode }) {
return shouldRenderChildren ? children : "default children";
}
// ⚠️ Caution: MySecondComponent may or may not render children.
<template.foo as={MySecondComponent}>Content</template.foo>;
function MyThirdComponent({ children }: { children: React.ReactNode }) {
return <div>{children}</div>;
}
// ✅ Allowed: MyThirdComponent always returns unmodified children.
<template.foo as={MyThirdComponent}>Content</template.foo>;
If you are using typescript, compiler won't allow you to specify a component
whose children
is not assignable to ReactNode