-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow static children in shadow: false mode #56
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works as it should
Author: jvdsande Date: 6. Jan 2021 Reference: preactjs#56
{ | ||
name, | ||
shadow, | ||
addContextListener(listener, element = cn[i]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't work as expected. When called via addContextListener(this._listener);
(see Line 148) element
is undefined.
I fixed this by defining a const childElement = cn[i];
at the beginning of the for
loop and using childElement
instead of cn[i]
. So in this case the line would be:
addContextListener(listener, element = childElement) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can see this seems to be a transpiler (in my case rollup) bug...
Rollup transpiles from
let i = 0;
for (i = 1; i--;) {
do_something_with(cn[i])
}
to code like
var i = 0;
function _loop() {
do_something_with(cn[i])
}
for (i = 1; i--;) {
loop();
}
Which doesn't make any sense....
addContextListener(listener, element = cn[i]) { | ||
element.addEventListener('_preact', listener); | ||
}, | ||
removeContextListener(listener, element = cn[i]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same Problem here as in 148
What does this PR do
This PR allows passing children for elements even with
shadow: false
. It only works for first render, if the children are modified after first render (i.e. if the element is used in a framework such as LitElement), children are not updated.It also cleans up the overall usage with
shadow: false
by getting rid of the<slot>
wrapper element, attaching thecontext
event listener on the custom element itself.Why is this PR needed
It partly fixes #41.
Children are a big part of a component design, not being able to pass children is a strong limitation. As of now, passing children results in them being duplicated. With this PR, at least the initial rendering is correct. It also enables internally handled children to be hydrated when using SSR.
Taking the following example:
The resulting markup without this PR is:
With this PR, it becomes:
Implementation details
This PR touches at various points of the wrapper's lifecycle. The first breaking change here is the addition of the following in
toVdom
:This snippet removes all children present in the original element before rendering (and after having copied them to the vDom's children), thus removing the duplicated/wrongly placed children.
The PR also removes the manual call to
connectedCallback
when handling props update before initial render. In place, it stores the props in the_props
temporary variable, so that they are applied at first render. This allows to avoid a bug where the component is rendered inside itself whenconnectedCallback
is called multiple time.The rest is implementation details about removing the
<slot>
element when not using ShadowDOM, has it is not needed.Misc
Removing the
<slot>
wrapper when not using ShadowDOM allows for a cleaner DOM, but it does come at a cost: we loose the ability to unregister the_preact
event listener. We could add this ability back by using auseEffect
hook in theSlot
component, but I did not want to add a dependency onpreact/hooks
there, since the library seems to avoid it.The usage is also a bit strange since modifying the children of the custom elements will not update the children of the Component, since it does not call
attributeChangedCallback
. I've not found a way around this.Finally, maybe handling children with non ShadowDOM is not something you want to be allowed, in which case this PR can just be closed 🙂