I have two Svelte components, a Parent and a Child. The Parent has an item. The Child has a button. When you click the Child button, the click handler should toggle a boolean in the Parent's item.
I expected the Child to be re-rendered because I passed it a new value. I want the text label on the button to toggle between "open" and "close".
What actually happens is nothing.
<script>
// Parent.svelte
import Child from "./Child.svelte";
let item = {id: 1, open: false};
function onToggle(e) {
item = {...item, open: !(item.open)};
console.log("onToggle:", item);
}
console.log("Parent:", item);
</script>
<Child
open={console.log("Child prop:", item), item.open}
onToggle={onToggle} />
<script>
export let open = false;
export let onToggle = null;
let buttonLabel = "open";
if (open) {
buttonLabel = "close";
}
console.log(`Child: open=${open}; buttonLabel=${buttonLabel}`);
</script>
<button on:click={onToggle}>{buttonLabel}</button>
After clicking the button a few times this is what I see. It seems like item.open
is being toggled, but Child isn't being re-rendered with the new value.
"Parent:" { id: 1 ,open: false }
"Child prop:" { id: 1 ,open: false }
"Child: open=false; buttonLabel=open"
"onToggle:" { id: 1 ,open: true }
"Child prop:" { id: 1 ,open: true }
"onToggle:" { id: 1 ,open: false }
"Child prop:" { id: 1 ,open: false }
Also, for the sake of simplicity, in this example the Parent only has a single item defined, but the code I'm working on has an array of items.
CodePudding user response:
Have a look at the $: marks a statement as reactive section in the docs and these tutorial sessions #1 #2
<script>
export let open = false;
export let onToggle = null;
$: buttonLabel = open ? "close" : "open"
$: console.log(`Child: open=${open}; buttonLabel=${buttonLabel}`)
</script>
{open}
<button on:click={onToggle}>{buttonLabel}</button>
(works without the log on the component... don't think it's a good idea to put it there)