Open EmmanuelOga opened 3 months ago
Neat idea! Another option that would be similar but avoid having to inject into props would be to expose it via context with a $
-prefixed name so it's super unlikely to clash with an existing context key and nicely marks the value as being an element. In Preact, context
is already passed as the second argument to function components (and the third argument to class component render methods):
function MyComponent(props: Props, { $host: HTMLElement }) {
useEffect(() => {
const handler = (ev: Event) => { /* ... */ };
$host.addEventListener("my-event", handler);
return () => $host.removeEventListener("my-event", handler);
});
return <div>...content...</div>;
}
register(MyComponent, "my-component", ["prop1", "prop2"]);
That sounds neat! But I'm not sure how it would be implemented 😅
If I get it right, the context here is retrieved from a parent, so I'd need to check that the context there is null/undefined?
const context = event.detail.context ?? { $host: this._root }
... something like that? I haven't needed slots
so far so I'm not sure if that is correct ... 😬
NOTE: this a "show don't tell" PR, and I'm guessing it may require changes to other parts of the library, but before adding docs or tests, I want to test the waters.
Working with custom elements, it is almost always necessary (except for the simplest of components) to get a hold of the root of the element, for instance to register event handlers to communicate with other parts of the DOM.
So, a Web component needs to do something like this:
I propose adding the root element as prop. This is a very minimal change that would make the API a lot cleaner:
This is just one option, another one could be to have some sort of hook to pick up the root element, but I think that would be a bit more complicated to setup. I like this change because is very minimal and should not even conflict with people that already have that prop name (unlikely as that might be).
Also, since the Component function is always called after the DOM element has been instantiated, it makes sense to make it available to the component without needing to use a Ref.