Closed iogrt closed 5 years ago
you can take a look here: https://dev.to/pinguxx/easy-apps-with-hyperhtml-3-1m3l im usng state using component, but i believe it can be done without the component part and use re-rendering using the function that bind returns
beside following the excellent @pinguxx tutorial, you could also use a simple utility that automatically update the component when its related properties change.
const AutoUpdate = Component => function (props) {
if (!AutoUpdate.$.has(props)) {
AutoUpdate.$.add(props);
Object.keys(props).forEach(key => {
const desc = Object.getOwnPropertyDescriptor(props, key);
if (desc.configurable) {
if ('value' in desc) {
let {value} = desc;
delete desc.value;
delete desc.writable;
desc.get = () => value;
desc.set = $ => {
value = $;
Component.apply(this, arguments);
};
Object.defineProperty(props, key, desc);
} else if ('set' in desc) {
let {set} = desc;
desc.set = $ => {
set.call(props, $);
Component.apply(this, arguments);
};
Object.defineProperty(props, key, desc);
}
}
});
}
return Component.apply(this, arguments);
};
AutoUpdate.$ = new WeakSet;
With above utility, you can setup your component as such:
const Button = AutoUpdate(props => wire(props)`
<button onclick="${props.onclick}">
${props.text}
</button>`);
and then render it through any object with properties that will automatically update the view when any of the properties changes:
function render() {
bind(document.body)`<div>
Lorem Ipsum
${Button(props)}
</div>`
}
render();
You can see a live working demo of above example.
I hope these two answers helped 👋
@Duarte-Dias I've also created a simple components based projects where you just pass any model/store/props to any component and everything magically happens without you needing to taking care of anything.
It's called hypersimple, and the most basic example is based on yours:
import {comp, html, render} from 'hypersimple';
// components
const Button = comp(model => html`
<button onclick=${model.onclick}>
${model.text}
</button>
`);
// main App: just like any component
const App = comp(model => html`
Lorem ipsum: ${model.count}
<br>
${Button(model.button)}
`);
// model: it will be mutated to trigger updates on changes
const model = {
count: 0,
button: {
text: 'increment',
onclick() {
// will update the view right away
model.count += 1;
}
}
};
// render
render(document.body, () => App(model));
You can see it live in this Code Pen.
Wow, your solution is brilliant! I bumped my head many times trying to implement this AutoUpdate but I lack these deep javascript skills.
I actually started looking for other tools in the meantime and found Choo.js, but that solution still uses dom-diffing and is a little bit more "frameworky" than I'd like.
I will definitely go back to hyperHTML / hypersimple and try this. Once again, congratulations on your amazing work!
First of all, thank you for building this library, I believe it's the start of a revolution in frontend development when people realise the disadvantages of working with such a big stack and fragile technologies.
I'm a big fan of "React-style" function components, and I love how simple it is in hyperHtml without any use of JSX.
The last obstacle I am facing before starting a hyperHTML project is how would I use a store. If I do something like this:
The button won't reload on rerender, which is awesome, but if this component uses some kind of state:
The component won't rerender with state, and if I create a new object in the render function with the state, the component will always rerender.
I want to only rerender if the state used changes, is something like this possible? I haven't found a solution yet.
I don't worry much if the performance is a bit worse, this is just a fun side project for myself.