Home > Back-end >  Why is my Svelte component not being rerendered despite passing in new prop values?
Why is my Svelte component not being rerendered despite passing in new prop values?

Time:01-08

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)

  • Related