Skip to content

Overzealous updating of components when using {#each} on array of objectsΒ #4695

@rdb

Description

@rdb

There's some awkward behaviour of Svelte that looks to me like a potential performance pitfall, and it occurs when iterating over an array of objects with {#each} and passing an element to a child component. For example:

{#each array as item (item.id)}
  <Item item={item} />
{/each}

The problem is this: if I add a new object to the end of the array, Svelte will update all the Item components, not just the one I added. This is demonstrated in this REPL (open the JS console to see the updates). This doesn't happen when it's an array of strings or numbers.

I think that the function safe_not_equal() is used for this, which never sees objects as equal, even identical ones. While I understand why this would be so in some cases (eg. a = a; should work for objects), it's less clear to me why this should also apply when updating a keyed "each" in this fashion.

I understand that there are several workarounds for this. I could destructure the object, but in my case it's very inconvenient for this component to have to know all the internals of my item model. I could mark the Item component as immutable, and this certainly works as expected, but this isn't very satisfying because this applies to all properties, and I don't want that in my case.

Perhaps there is a good technical reason for it to work like this? If so, I think this should be documented so that others don't trip over this. If not, please consider this my humble request to change this behaviour.

Oh, and thanks so much for creating such a great library! I don't think I'll be able to ever go back to React now that I've tried Svelte.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions