As explained in here, I'd like to know if there's any interest in improving the current transformation or if I should just fork this and try to make it work as intended.
There is a little, but huge, change that opens doors for this transformation in a pretty seamless way.
JSX
const { Component, bind } = hyperHTML;
class Rando extends Component {
render() {
return this.html(
<Sub value={1 + this.props.rand} />
<Sub value={2 + this.props.rand} />
);
}
}
class Sub extends Component {
render() {
return this.html(
<div>
Value <strong>{this.props.value}</strong>
</div>
);
}
}
const render = bind(document.body);
render(
<div>
<Rando rand={Math.random()} />
</div>
);
should become
const { Component, bind } = hyperHTML;
class Rando extends Component {
render() {
return this.html`
${node => {
const comp = Sub.for(node);
comp.props = {value: 1 + this.props.rand};
return comp.render();
}}
${node => {
const comp = Sub.for(node);
comp.props = {value: 2 + this.props.rand};
return comp.render();
}}
`;
}
}
class Sub extends Component {
render() {
return this.html`
<div>
Value <strong>${this.props.value}</strong>
</div>
`;
}
}
const render = bind(document.body);
render`
<div>
${node => {
const comp = Rando.for(node);
comp.props = {rand: Math.random()};
return comp.render();
}}
</div>
`;
enabling the following features:
- no component trashing. Every component is related to their template comment node and created only once.
- there are props, not just state. When the
.render()
will be automatically invoked the component would already have updated props (or the same if not computed at runtime).
- simple and semantic, hiding boilerplate all over, granting unique IDs per each component relation
How to transform
The rule is pretty simple:
<ComponentName attr1={123} attr2=456 attr3={what('ever')} />
Should become
${node => {
const comp = ComponentName.for(parent);
comp.props = {attr1: 123, attr2: 456, attr3: what('ever')};
return comp.render();
}}
So that attributes would be passed as props.
The Template Literal rules
The JSX surrounding parenthesis will mark the beginning and the end of the Template Literal, and holes found outside components should be replaced by ${}
instead of {}
so that this:
render(
<div onclick={event => alert(event.target)}>
<Comp stuff={'cool'} />
</div>
);
would become
render`
<div onclick=${event => alert(event.target)}>
${node => {
const comp = Comp.for(node);
comp.props = {stuff: 'cool'};
return comp.render();
}}
</div>
`;
I hope all details are clear enough.
TBD
I am not sure it makes sense to pass along children, since each component can create those directly in the render method, and use props to define children, i.e.
<ComponentName sub={['first child', 'last child']} />
So, actually, I think for the time being having just the proposed transform would be awesome.
Thank You !!!
You had this idea and I'm trying to make it happen for the whole hyperHTML user-base, which I'm pretty sure would appreciate the possibility of using JSX to simplifying lightweight components usage in hyperHTML instead of Custom Elements.
Thanks in advance for considering this or, eventually, for sharing your thoughts on this.
Best Regards.
Code Pen live here https://codepen.io/WebReflection/pen/MPxBzJ?editors=0010