Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Array mutation doesn't update #2362

Closed
asyncmax opened this issue Apr 6, 2019 · 8 comments
Closed

Array mutation doesn't update #2362

asyncmax opened this issue Apr 6, 2019 · 8 comments

Comments

@asyncmax
Copy link

asyncmax commented Apr 6, 2019

First of all, I finished v3 tutorial and Svelte is amazing. Thanks for making this.
I am exploring Svelte's internals and found a behavior that I couldn't understand.

https://v3.svelte.technology/repl?version=3.0.0-beta.22&gist=1d7388842c1b334366fd60f53fc5c2d9

<script>
  let items = [1, 2];
  let data = {count: 1};

  function add() {
    items.push(items.length + 1);
  }

  function inc() {
    data.count++;
  }
</script>

<ul>
  {#each items as item}
    <li>Item: {item}</li>
  {/each}
</ul>

<button on:click={add}>Add</button>

<div>Count: {data.count}</div>

<button on:click={inc}>Inc</button>

In default immutable: false mode, The array mutation doesn't update whereas object mutation does. Is this by design? I am using 3.0.0-beta.22.

@Panya
Copy link
Contributor

Panya commented Apr 6, 2019

See the issue #2243

@Conduitry
Copy link
Member

Yep, this is by design. Svelte doesn't treat .push() calls differently than any other method calls on object - none of them will cause a re-render of that data. You can use items = items; which will get compiled away and trigger an update. This just hasn't made its way into the tutorial and API docs yet.

@asyncmax
Copy link
Author

asyncmax commented Apr 6, 2019

Thanks, guys.

I momentarily thought arrays might deserve special treatment, considering the array mutation is such a common pattern, but realized it is straightforward concept once we learn why. I also love the workaround - simple and intuitive.

@Cweili
Copy link

Cweili commented May 8, 2019

Yep, this is by design. Svelte doesn't treat .push() calls differently than any other method calls on object - none of them will cause a re-render of that data. You can use items = items; which will get compiled away and trigger an update. This just hasn't made its way into the tutorial and API docs yet.

This may seem odd for array mutation, but it's a reasonable design.

@AltarnRain
Copy link

AltarnRain commented Jun 5, 2019

You can use:

arr = [...arr, newValue];
arr = [newValue, arr];

This will trigger an update. Unfortunately you're also creating an entirely new array. Not the neatest solution but it works.

@davidsavoie1
Copy link

Hi! I don't really know where to post my related question, but here it is... I'm used to working immutably in Javascript, especially using the Ramda library. In Svelte, is it idiomatic, when updating an array or object, to make a new version immutably and only reassign it to the same variable?

This will trigger an update. Unfortunately you're also creating an entirely new array. Not the neatest solution but it works.

@AltarnRain Why do you say it is unfortunate? Performance problems? And what would be the neatest solution then?

What are the performance implications if, in the example below, I change the value of entity bar from 2 to 3, considering that assoc creates a new value without mutating the original one? Does it trigger a change only on the components that reference entity bar, or any component that references the entire entitiesById object?

let entitiesById = {
  foo: { _id: "foo", value: 1 },
  bar: { _id: "bar", value: 2 },
};

const modifiedBar = R.pipe(
  R.prop("bar"),
  R.assoc("value", 3)
)(entitiesById);

entitiesById = R.assoc("bar", modifiedBar, entitiesById);

// {
//   foo: { _id: "foo", value: 1 },
//   bar: { _id: "bar", value: 3 },
// }

Thanks a lot!

@JustinRademaker1994
Copy link

JustinRademaker1994 commented Jan 6, 2024

The documentation says: "Because Svelte's reactivity is based on assignments, using array methods like .push() and .splice() won't automatically trigger updates. ". But doesn't an assignment occur internally, behind the scenes of the .push() method? And therefore, following the logic, an update should be triggered?

Or do we ignore the internals of build-in functionality? Or maybe something else is going on? This confuses me a bit.

@Antonio-Bennett
Copy link

@JustinRademaker1994 In svelte 5 array mutation methods work :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants