WebReflection / hyperHTML

A Fast & Light Virtual DOM Alternative
ISC License
3.06k stars 112 forks source link

Only last element renders when reusing #401

Closed sidvishnoi closed 3 years ago

sidvishnoi commented 3 years ago

I maybe misunderstanding how hyperHTML works, but in the first case of the example below, only the last usage of icon is rendered. Does hyperHTML move the elements into the DOM instead of cloning them?

See minimal reproduction: https://codepen.io/sidvishnoi/pen/VwaqwzM

// Case 1:
const icon = hyperHTML`<em>🚫</em>`;
for (const num of [1, "2", "3 only last SVG is rendered"]) {
  const contents = [];
  contents.push(hyperHTML`<span>${icon} ${num}</span>`);
  // ... 
  document.getElementById("main1").append(hyperHTML`<h2>${contents}</h2>`);
}

// Case 2:
for (const num of [4, 5, 6]) {
  const icon = hyperHTML`<em>✅</em>`;
  const contents = [];
  contents.push(hyperHTML`<span>${icon} ${num}</span>`);
  // ...
  document.getElementById("main2").append(hyperHTML`<h2>${contents}</h2>`);
}

console.log(document.getElementById("main1").innerHTML);
console.log(document.getElementById("main2").innerHTML);
WebReflection commented 3 years ago

have you tried to use wire?

const icon = hyperHTML.wire()`<em>🚫</em>`;
for (const num of [1, "2", "3 only last SVG is rendered"]) {
  const contents = [];
  contents.push(hyperHTML.wire()`<span>${icon} ${num}</span>`);
  // ... 
  document.getElementById("main1").append(hyperHTML`<h2>${contents}</h2>`);
}
WebReflection commented 3 years ago

Actually ... wait a minute ... yes, hyperHTML optimize the hell out of everything, never cache content if you want to use it in multiple places ... it's also not necessary, nor faster, it's just error prone, due referenced content/nods that are of course moved around when cached, that's the point of caching.

Either wire content with different IDs, or simply create a new element within each loop, as you want a different element within each loop.

sidvishnoi commented 3 years ago

That makes sense, though my intention of keeping the content out of the function was for clarity, instead of optimization. Thanks for clarifying!

WebReflection commented 3 years ago

if that's the intent, make it arrow?

const icon = () => hyperHTML`<em>🚫</em>`;
for (const num of [1, "2", "3 only last SVG is rendered"]) {
  const contents = [];
  contents.push(hyperHTML`<span>${icon()} ${num}</span>`);
  // ... 
  document.getElementById("main1").append(hyperHTML`<h2>${contents}</h2>`);
}
sidvishnoi commented 3 years ago

Appreciate the suggestion, though we went with cloneNode() instead.

WebReflection commented 3 years ago

free to do whatever you prefer, but the whole point of this library is that you don't need to use DOM APIs ... it's better to understand how these work, imho 👋