WebReflection / heresy

React-like Custom Elements via V1 API builtin extends.
https://medium.com/@WebReflection/any-holy-grail-for-web-components-c3d4973f3f3f
ISC License
276 stars 16 forks source link

Inconsistent list rerendering after removing items #27

Closed doorgan closed 4 years ago

doorgan commented 4 years ago

Hi, I'm trying to render a list of files previews, but when I delete an item, only the last item in the list gets removed from the rendered result, in a way that the rendered list does not represent the actual list. It seems heresy is rendering a list with the new length but the old data.

The codesandbox I'm experimenting with is here: https://codesandbox.io/s/recursing-river-pur4i

Steps to reproduce:

Relevant snippets:

// src/editor/index.js

remove_file(file) {
  this.files = this.files.filter(x => x.id !== file.id);
}

// on render()
const remove_file = e => {
  this.remove_file(e.target.file);
};
// ...
this.html`
<!-- ... -->
<div class="media-list">
   ${this.files.map(
     file => html`
      <MediaItem .file=${file} onremove=${remove_file} />
     `
  )}
</div>
<!-- ... -->
`

Is this a bug, or is there something I'm missing? The linked codesandbox is pretty much barebones repro as I'm just trying out heresy, but please do let me know if you need an even simpler one.

I'm using Array.filter and Array.map, I've also tried with Object.keys like in heresy-todo, but it yields the same result.

WebReflection commented 4 years ago

this is an example where using keyed lists become mandatory:

${this.files.map(
            file => html.for(this, file.id)`
              <MediaItem .file=${file} onremove=${remove_file} />
            `
          )}

the reason is that otherwise each time the list changes you would end up re-parsing every single file, but since you do that only within the oninit event, which never triggers again, you won't see the changes applied.

In few words, everything works fine if:

I've explained this in more details in here: https://github.com/WebReflection/uhtml/blob/master/DOCUMENTATION.md#the-forref-id-tag

it's uhtml but it has exact same lightrerhtml API (which is the one used in heresy)

doorgan commented 4 years ago

Oh, that makes a lot of sense. Thanks!