I’m curious about Html.keyed. The docs say it “makes it possible for the underlying diffing algorithm to reuse nodes more efficiently.” Is it exclusively for performance benefits, or is it important to use any time you have a reorderable list? I’m also curious about how unique the keys have to be, and how dangerous changing them would be. Does hashing the content of a node for use as a key make sense?
Here’s the reason I’m asking:
I have a large data structure (a tree) that represents the structure of an email. It’s basically [[[[Node]]]]. Users can move nodes around in the structure, and we are getting some problems I think might be related to the virtual DOM reusing nodes. We aren’t currently giving everything unique IDs or using Html.keyed, so I assume that’s where some of the app’s odd behavior is coming from.
A few details:
JS libraries handle some of the content of the nodes, for wysiwyg functionality and color pickers, and we request the changes through ports. This complicates things.
the user can add, delete, and re-order nodes
unexpected behavior includes some edits affecting other nodes (mostly the background color of nodes behaving strangely when they are moved). I tried adding keyed but we don’t have unique IDs attached to all the nodes, so I’m curious about constraints on these IDs.
Yes the weird behaviour sounds like it would be fixed by using keys.
It’s because of how the diffing works. To simplify it a bit, the algorithm can’t distinguish between these two cases:
Inserting a new item halfway through a list
Modifying every item below halfway, while adding an extra item at the same time
That doesn’t matter unless the elements in the list contain some state that Elm doesn’t know about. This seems to be your case.
This issue arises with all virtual DOM libraries, including React. There’s a good explanation at the following link. Pay particular attention to “recursing on children” and “keys”.
In terms of “how unique”, all children of the same parent element in the DOM should have different keys. But you can reuse those keys elsewhere if you like.
The uniqueness erequirementrs are actually looser because the Elm DOM diff only does, I believe, a one element look ahead which means that they really only need to be “locally” unique.
The impacts of this implementation are that:
• Keys, if unique, are sufficient to prevent reuse because a key mismatch will `prevent reuse.
• If the total number of DOM structure changes between animation frames is small enough then keys can help encourage reuse by helping the DOM diff algorithm find correspondences between frames but this only works to the extent that the changes involve isolated single element insertions or deletions.