Matt-Esch/virtual-dom

Use `id` properties to match elements in diff

tdammers opened this issue · 1 comments

When diffing a VDOM, I sometimes want to explicitly mark elements in the old and new trees as being "the same object", such that rather than removing them and inserting a new one, or updating another node with the new properties. For example, if I have these trees:

// old
h('div', {}
    [
        h('img', { src: '1.png', id: 'img-1' } [],
        h('img', { src: '2.png', id: 'img-2' } []
    ]
)

// new
h('div', {}
    [
        h('img', { src: '2.png', id: 'img-2' } []
        h('img', { src: '3.png', id: 'img-3' } []
    ]
)

...then there are two possible ways of patching this:

a) update first image, setting src = 2.png and id = img-2, update second image, setting src = 3.png and id = img-3
b) remove first image, insert new image with src = 3.png and id = img-3

It seems that virtual-dom prefers option a), however if both images have fixed positions, then this leads to rendering artifacts during the update: the 2.png image will temporarily appear in two places, until 3.png finishes loading and replaces the image data in the second image, because the image element is still the same, and will keep showing the previous image until the new one loads. At least that's how I explain the artifacts I'm seeing.

Now, react.js's DOM differ seems to take the id property into account when diffing, trying to maintain the id / DOM object identity as much as possible, which would pretty much solve the issue at hand. Is it possible to get a similar behavior with virtual-dom?

virtual-dom uses key to identify dom nodes between renders. Give that a shot. You also may need to look out for transforms or opacity or anything that causes a new rendering context, these can cause all kinds of artifacting if done wrong.... or right.