hyperHTML: Uncaught DOMException: Failed to execute 'insertBefore' on 'Node'
I think I have a fundamental misunderstanding of how the library actually works so I don’t think this is an issue with the library however below is my code and the error I get, I am not sure why this happens.
import { wire, bind } from "hyperhtml/esm";
window.wire = wire;
window.bind = bind;
var appRoot = document.getElementById("root");
var appRenderer = bind(appRoot);
// appRenderer is a function which takes 1 parameter: template
// I should call appRenderer with a template (``) everytime I want to update the UI.
function UI() {
var timerInstance = timer(0, notify);
var timerInstance2 = timer(0, notify);
function render(){
return wire()`${timerInstance.render()}, ${timerInstance2.render()}`;
};
function notify(){
console.log("I am notified!")
subscriber(render());
}
var subscriber;
return {
subscribe: function (f) {
subscriber = f;
}
, notify: function(){
notify();
}
}
}
function timer(start, notify){
var counter = start;
var template = wire()`hi ${counter}`;
setInterval(function(){
counter++;
template = wire()`hi ${counter}`
notify();
}, 2000)
return {
render: function(){
return template;
}
};
}
var ui = UI();
ui.subscribe(function (template) {
appRenderer`${template};`
})
ui.notify();
I am notified!
bundle.js:956 Uncaught DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.
at domdiff (http://localhost:9000/dist/bundle.js:956:20)
at Array.anyContent (http://localhost:9000/dist/bundle.js:10491:99)
at Array.update (http://localhost:9000/dist/bundle.js:855:16)
at HTMLDivElement.render (http://localhost:9000/dist/bundle.js:828:12)
at http://localhost:9000/dist/bundle.js:9968:16
at notify (http://localhost:9000/dist/bundle.js:9934:9)
at http://localhost:9000/dist/bundle.js:9956:9
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 24 (13 by maintainers)
one is a cached reference to a template literal tag function and another one create a new template literal tag function every single time?
yes, or you’ll trash same question content every time, including its state in terms of DOM tree/render/status
you weakly relate some content to some data. that means hyperHTML directly update interpolations of the template. You can see that via debugger.
if you don’t relate content to any data, you create new content every single time.
This is never what you want so either you scope
const render = wire()
and you use thatrender
to return and update the related dom, you you canwire(data)
and use it to update data.Have a look at this little explanation of how things work here: https://gist.github.com/WebReflection/d3aad260ac5007344a0731e797c8b1a4
bind or wire doesn’t matter, wire has no parentNode, bind is the parentNode
every time you
wire()
without passing a reference you lose the previous content and create new content from the scratchwire()
creates a new DOM element/structure every single timeyou are also using zero DOM in the whole example … there’s nothing that actually needs a DOM node.
if you use modules you don’t need to export to the window anything, but I guess this was for testing purpose.
If you change the template value every single time, you are passing a new node. This is not really the way to go. If you want dynamic content you should use an array, so it can grow, reset, or change in the future.
but that’s not even it … you are trashing every time everything instead of updating the only thing you care about: the number:
noe everything is fine because you update some DOM weakly referenced instead of trashing layouts and trash in new layout per each update.
Basically lit-html does the weakly reference internally but it cannot render anywhere else outside its place in the template literal while hyperHTML let you wire any reference and reuse its content updating only what’s needed every single time.
You might also have found a weird edge case with all these new wires and I might have a look if something went wrong but for sure what you were doing was definitively not the way to use this library.
the quick summary:
You can always pre-address bound elements or wired objects as render and use them whenever it’s convenient.
Be sure you read all examples to better understand the logic.