Reputation: 1556
I have a component that maintains a selection as an array and a child component that determines its state by seeing if it is included in that array. When I change the array, the child component does not re-render. How do I fix this?
REPL: https://svelte.dev/repl/f2074ef75dee444faaee005b8b7cf9b9
App.svelte
<script>
import Nested from "./Nested.svelte";
let selection = [];
function isSelected(n) {
return selection.indexOf(n) > -1;
}
function click(e) {
const n = e.detail.number;
if (isSelected(n)) {
selection = selection.filter(x => x != n);
} else {
selection = [...selection, n];
}
console.log("Selection is", selection);
}
</script>
{#each [1, 2, 3] as number}
<Nested
{number}
selected={isSelected(number)}
on:click={click} />
{/each}
Nested.svelte
<script>
export let selected, number;
import { createEventDispatcher } from "svelte";
const dispatch = createEventDispatcher();
function click() {
dispatch("click", {
number
});
}
</script>
<style>
.selected {
color: red;
}
</style>
<div class:selected={selected} on:click={click}>
{number}
</div>
Upvotes: 4
Views: 1966
Reputation: 25001
The problem is this
selected={isSelected(number)}
In this expression:
isSelected(number)
Svelte will update for every change to any variable in the expression. That is: either isSelected
or number
.
In you case, you want to react to a change to selection
, and so it doesn't do it.
You can inline the condition, so that the selection
variable is directly mentioned in the expression:
selected={selection.indexOf(number) > -1}
Or you can just do that:
selected={selection, isSelected(number)}
The comma syntax x, y
is just somewhat obscure JS syntax for an expression which value resolves to the last item (try 'a', 'b', 'c'
in your console to see what I mean)... But in this case, it allows to hint Svelte that it should pay attention to the selection
variable here.
Upvotes: 1