Closed bcomnes closed 4 years ago
Is this whole idea stupid and I should give up?
no idea is stupid, it's eventually just a matter of understanding the idea value
import uce from 'uce-lib'
I don't even have a repository for that, and I think I should remove/deprecate already that package, but as you can read in npm: https://www.npmjs.com/package/uce-lib
This module does not inject µce in the page, you can still do that as part of the main bundle.
So here what I'd try, before blaming uce
// instead of import uce from 'uce-lib'
import 'uce';
// ... rest of the code ...
// instead of uce.then(uceNested)
customElements.whenDefined('uce-lib').then(() => {
uceNested(customElements.get('uce-lib'));
});
Anyway, I've written a CodePen and indeed nothing happens, 'cause the uce render is the same used in uhtml, but uland render needs to "unroll" its own hooks, due double pass on regular uhtml "holes".
However, even using explicitly the uland render function, it looks like within the uce render() it doesn't really work, and this is a bit of a bummer.
I'll have a look, but so far I think I'd like these libraries to be somehow interchangeable, hence it might be worth a fix/update where needed.
no idea is stupid, it's eventually just a matter of understanding the idea value
Maybe stupid is too harsh, I meant misguided.
This module does not inject µce in the page, you can still do that as part of the main bundle. So here what I'd try, before blaming uce
Oh yeah, sorry, I have a working uce solution in place with uce-lib but its not apparent by the example. My mistake. I'll switch to vanilla WC .get solution.
I'll have a look, but so far I think I'd like these libraries to be somehow interchangeable, hence it might be worth a fix/update where needed.
That would be cool. In the meantime it looks like heresy supports a web component wrapper with hooks if I really need a solution quickly. It would be cool of the u* family could compose. Feel free to close or leave open if you want a reminder to look into this.
Well, uce-template has hooks too, but it's more Vue-3-ish than React-ish, but yeah, having uland usable in uce looks like a reasonable request, I just don't know when I'll find the time to do that (soonish though, as I'm curious about why it doesn't work now as I'd expect).
I feel stupid ... it's solved: https://codepen.io/WebReflection/pen/QWExMeG?editors=0010
Basically, you need to use the render
and html
from uland, not the one provided by uce
import 'uce';
import {Component, html, render, useState} from 'uland';
const Counter = Component((initialState) => {
const [count, setCount] = useState(initialState);
return html`
<button onclick=${() => setCount(count + 1)}>
Count: ${count}
</button>`;
});
const uceNested = ({define, css}) => {
define('uce-nested', {
style: selector => css`${selector} {
font-weight: bold;
color: blue;
}`,
render() {
render(this, html`
<div>
Hello uce nested
${Counter(0)}
</div>`);
}
});
};
customElements.whenDefined('uce-lib').then(() => {
uceNested(customElements.get('uce-lib'));
});
That's why outside the define(...)
everything was working as expected, but using render
or html
, or even svg
, from uce, instead of uland, can't possibly work.
Alternative:
import {define, css} from 'uce';
import {Component, html, render, useState} from 'uland';
const Counter = Component((initialState) => {
const [count, setCount] = useState(initialState);
return html`
<button onclick=${() => setCount(count + 1)}>
Count: ${count}
</button>`;
});
define('uce-nested', {
style: selector => css`${selector} {
font-weight: bold;
color: blue;
}`,
render() {
render(this, html`
<div>
Hello uce nested
${Counter(0)}
</div>`);
}
});
Case solved 👋
Awesome! That should do it!
Another idea, to simplify the pattern:
import 'uce';
import {Component, html, render, useState} from 'uland';
function uland() { return render(this, html.apply(null, arguments)); }
const ulandify = self => Object.defineProperty(
self,
'html',
{value: uland.bind(self.html``)}
);
const Counter = Component((initialState) => {
const [count, setCount] = useState(initialState);
return html`
<button onclick=${() => setCount(count + 1)}>
Count: ${count}
</button>`;
});
const uceNested = ({define, render, html, svg, css}) => {
define('uce-nested', {
style: selector => css`${selector} {
font-weight: bold;
color: blue;
}`,
init() {
ulandify(this).render();
},
render() {
this.html`
<div>
Hello uce nested
${Counter(0)}
</div>`;
}
});
};
customElements.whenDefined('uce-lib').then(() => {
uceNested(customElements.get('uce-lib'));
});
This way you can use all uce utilities, when needed, and be sure you are in uland whenever a component passes through ulandify(element)
before render()
gets call.
P.S. above example needs latest uce as I had to make the html
property configurable to be able to do that. The key, in this approach, is that you don't need to import uce
per each uladn component you define, you can still use the customElements
bootstrap procedure and include uce once, while defining components via uland.
Even better
I really like the ergonomics of uland, but I want to deliver a web component as the consumption API of a component I'm writing. This attempt could be misdirected, but I was trying to figure out how to consume a uland component inside of a uce web component wrapper like this:
(to quickly expand, uce provides a nice web-component wrapper, but inside the component, I get the nice and simple DX from uland and have access to re-usable hooks.)
This doesn't work, nothing renders for
Counter
, and from what it looks like, it comes down to a difference in the render functions being used.Is this something that could be supported? Is there a better way to wrap a uland component in a a webCompoent wrapper similar to uce? Is this whole idea stupid and I should give up?