I'm trying to build a simple application with react and web ponents UI library.
This library uses named slots
in order to populate areas in the ponent.
When trying to use a named slot like this in my template:
<div slot="app-content"></div>
The rendered output is without the slot: <div></div>
Minimal reproduction:
Just add <div slot="mySlot" id="mySlottedDiv"></div>
to a react ponent's template. Then inspect the resulting HTML and see that the slot
attribute is omitted.
Here's an example of such an app: =/index.js
In this file, you can see I'm setting a div
with slot="app-content"
but the resulting HTML removes the attribute from the div
- hence preventing me from using the web ponent's API.
Is there a way to force react NOT to remove attributes from an element? Is this a bug in react?
I'm trying to build a simple application with react and web ponents UI library.
This library uses named slots
in order to populate areas in the ponent.
When trying to use a named slot like this in my template:
<div slot="app-content"></div>
The rendered output is without the slot: <div></div>
Minimal reproduction:
Just add <div slot="mySlot" id="mySlottedDiv"></div>
to a react ponent's template. Then inspect the resulting HTML and see that the slot
attribute is omitted.
Here's an example of such an app: https://codesandbox.io/s/vivid-spring-hack-react-example-forked-yu9dss?file=/index.js
In this file, you can see I'm setting a div
with slot="app-content"
but the resulting HTML removes the attribute from the div
- hence preventing me from using the web ponent's API.
Is there a way to force react NOT to remove attributes from an element? Is this a bug in react?
Share Improve this question edited Apr 21, 2022 at 15:13 yccteam asked Apr 21, 2022 at 15:01 yccteamyccteam 2,3114 gold badges29 silver badges51 bronze badges 7- 1 The way SO works, your whole question (including any necessary code) has to be in your question, not just linked. Three reasons: People shouldn't have to go off-site to help you; some sites are blocked for some users; and links rot, making the question and its answers useless to people in the future. Please put a minimal reproducible example in the question. More: How do I ask a good question? and Something in my web site or project doesn't work. Can I just paste a link to it? – T.J. Crowder Commented Apr 21, 2022 at 15:06
-
Try naming the attribute
data-slot
instead ofslot
.slot
is not a valid attribute on adiv
element and React knows this and that's why it sanitizes it. However, any attribute starting withdata-
are valid as they're specified as custom attributes. Hopefully the web ponents UI library you're using handles this and treatsdata-slot
the same asslot
. – Lennholm Commented Apr 21, 2022 at 15:07 - I found this: github./skatejs/skatejs/issues/1096 Apparently a known issue that can be circumvented by using Preact instead. I'm wondering why you want to cram web ponents into a React app anyway. – user5734311 Commented Apr 21, 2022 at 15:09
-
@Lennholm - the
slot
attribute has been around for years now and I'm using it natively. If what you say is true, thenreact
is wrong and has a major bug in it that prevents using a valid HTML standard. developer.mozilla/en-US/docs/Web/HTML/Global_attributes/… – yccteam Commented Apr 21, 2022 at 15:09 -
@ChrisG - thanks! I found this one as well, but using
preact
is not an option for us. We have our own web ponents library and it is web ponents based. The fact react does not support valid HTML syntax is a major issue IMO. – yccteam Commented Apr 21, 2022 at 15:11
3 Answers
Reset to default 2It seems like there are some issues opened and closed on some libraries trying to integrate with react to support slot
attribute properly.
This seems to be a solution that circumvents react whitelisted attributes:
function slot(name = "") {
return { ref: (e) => e.setAttribute("slot", name) };
}
and then render:
<div {...slot("app-content")}>
This seems to work.
Here there are some more info: https://github./skatejs/skatejs/issues/1096 https://codesandbox.io/s/vivid-spring-hack-react-example-forked-nik1hs?file=/index.js
Ok, apparently this is working in react version 16 and above. Here's the blog post that explains that: https://reactjs/blog/2017/09/08/dom-attributes-in-react-16.html In my case, it is solved by upgrading react.
I just created a ponent for myself.
import * as React from 'react';
type SlotProps = {
name: string;
isDefault?: boolean;
};
export const Slot: React.FC<React.PropsWithChildren<SlotProps>> = ({
name,
isDefault,
children,
...props
}) => {
return (
<>
{React.Children.toArray(children).filter((child) => {
if (React.isValidElement<{ slot: string }>(child)) {
return (
child.props.slot === name ||
(!child.props.slot && isDefault)
);
}
return isDefault;
})}
</>
);
};
which can be used in a ponent like this:
const Component = ({children}) => (
<div>
<h1>Component</h1>
<Slot name="content">{children}</Slot>
</div>
)
an by others like this:
<Component>
{{
content: <p>Hello World!</p>
}}
</Component>
or
<Component>
<p slot="content">Hello World!</p>
</Component>