Search code examples
javascripthtmlframeworksreactive-programmingsvelte

svelte component not rerender conditionals in child component with data of parent component with {#each} loop


the complete code is here: https://svelte.dev/repl/a2af19fc79e246f9956968db9c2f5aa6?version=3.50.1

basically, at the first click, everything works fine

but when you click the second time everything is broken.


✅ WHEN WORK FINE:

enter image description here

❌ WHEN DON'T WORK:

enter image description here

I am trying to see where is the bug for 2 days now,

and I found that if I try to console.log() my conditionals the first time it will console, but the second time not.


the data is got from the parent to the child.

and the data is an array, and we loop on it and for each item, we create a child.

so changing the array in the parent should trigger rerender also in the child.


at some point this was a lot of debugging for me, so I tried to convert all my variables to $:

and still don't work.

but technically should work also with const since we recreate a new line from scratch (@each)


from what I see the data is passed correctly and also console.log every time.

but conditionals like sameY = y === prevY;
don't get rerender when y or prevY get rerendered


here where the values should be correct (inside Gline.svelte)

<div
  class="h-px bg-cyan-500 absolute origin-bottom-left"
  style="width:{setLineWidth()}px; transform:translate({prevX}px, {prevY}px) rotate({setLineAngle()}deg);"
  transition:scale
/>

you see there is setLineWidth(), {prevX}, {prevY} variables that need to change.

and technically first time change correctly but other times don't do it.


I am asking if someone can know why and show me I can fix it.

I am open to suggestions if you want


Solution

  • For performance reasons, the #each by default does not fully recreate everything, instead it adds or removes items at the end. To circumvent this, a key can be provided in parentheses at the end.

    The key has to uniquely identify the object; usually something like a number or string is used so unchanged items do not have to be recreated (e.g. if an item is inserted in the middle, all other items remain the same).

    Here you can just specify the whole item, as the reference will change, so it will update everything correctly:

    {#each coordsArray as thisCoords, index (thisCoords)}
    

    Docs for #each