Bug: why does using keys produce seemingly random duplicates?
See original GitHub issueDescribe the bug
The deeper you go, the more likely you are to hit this issue. For instance, a top-level wrapper with ONLY_KEYED_CHILDREN
and unique keys appears to work fine. But nest it within another element as a wrapper, and duplicates start appearing after adding maybe 3 items.
Reproducing this in a basic page like this was a nightmare. 🥵 I still haven’t actually reproduced the issue I was originally troubleshooting, which was adding 6-8 duplicate items when inserting one (deleting it from the context/state deleted all 6-8 dupes of the row).
Here’s an example:
<!DOCTYPE html>
<body>
<div id="app"></div>
<script type="module">
import {
m,
patch,
VFlags
/* or any other exports you want to access */
} from 'https://unpkg.com/million?module';
const format = new Intl.DateTimeFormat('en-us', { dateStyle: 'short', timeStyle: 'medium' });
let dates = [];
function render() {
dates.push(new Date());
let vdom = m(
'div',
{ id: "app" },
[
m('div', undefined, dates.map(dt => m('div', { key: dt.getTime().toString() }, [format.format(dt)])), VFlags.ONLY_KEYED_CHILDREN)
]
);
console.log('render', vdom);
patch(document.getElementById('app'), vdom);
}
setInterval(render, 1000);
render();
</script>
</body>
To “fix” this behavior, just remove the VFlags.ONLY_KEYED_CHILDREN
and the default diffing works fine. Even more strange: remove the .wrapper
element and make the date entries direct children of the #app
element and it works again.
To Reproduce
This behavior appears to be part of the diffing when using keys with ONLY_KEYED_CHILDREN. What confuses me is why it only happens after it’s nested below the top-level. I’ve spent time trying to review the children driver for diffing, and haven’t noticed anything obvious.
To reproduce this:
- Nest the children one level deeper than the top, or more.
- Add keys on each element.
- Add
VFlags.ONLY_KEYED_CHILDREN
on the parent/wrapper node.
Expected behavior
Yeah, only 1 item should be added per keyed item.
Screenshots
Operating System
MacOS Catalina 10.15.7 (19H1419)
Browser
Chrome 94; FireFox 93
Additional context
No response
Issue Analytics
- State:
- Created 2 years ago
- Comments:8 (4 by maintainers)
Top GitHub Comments
So, I’m still testing out things with 0.6.7 and I noticed that in addition to fixing the glitches with nesting keyed items, performance had a huge improvement. With v0.6.7 the performance is looking like:
patch()
now takes an average of 5-7ms. This is easily 6x better than my earlier optimizations, if not faster still, and is consistently this fast. In fact, it took a bit before it reached 5-7ms render time—before that it was in microseconds.🤯 🚀
I still haven’t even played with the ignore property/flag. (Which I’ll probably do in the various static regions after the first render.)
Awesome! I’ll probably have it stress tested on Monday. 😉 Thanks for the quick support, and hard work on this project!