Because Svelte's reactivity is triggered by assignments, using array methods like push
and splice
won't automatically cause updates. For example, clicking the 'Add a number' button doesn't currently do anything, even though we're calling numbers.push(...)
inside addNumber
.
One way to fix that is to add an assignment that would otherwise be redundant:
function addNumber() {
numbers.push(numbers.length + 1);
numbers = numbers;
}
But there's a more idiomatic solution:
function addNumber() {
numbers = [...numbers, numbers.length + 1];
}
You can use similar patterns to replace pop
, shift
, unshift
and splice
.
Assignments to properties of arrays and objects — e.g. obj.foo += 1
or array[i] = x
— work the same way as assignments to the values themselves.
function addNumber() {
numbers[numbers.length] = numbers.length + 1;
}
A simple rule of thumb: the name of the updated variable must appear on the left hand side of the assignment. For example this...
const obj = { foo: { bar: 1 } };
const foo = obj.foo;
foo.bar = 2;
...won't trigger reactivity on obj.foo.bar
, unless you follow it up with obj = obj
.
<script>
let numbers = [1, 2, 3, 4];
function addNumber() {
numbers.push(numbers.length + 1);
}
$: sum = numbers.reduce((total, currentNumber) => total + currentNumber, 0);
</script>
<p>{numbers.join(' + ')} = {sum}</p>
<button on:click={addNumber}>
Add a number
</button>