svelte icon indicating copy to clipboard operation
svelte copied to clipboard

$: reactive statement ignored during beforeUpdate

Open ibmua opened this issue 2 years ago • 1 comments

Describe the bug

$: reactive statements are ignored if values are modified in beforeUpdate.

Reproduction

Solve https://learn.svelte.dev/tutorial/update and add

	$: {
		console.log("autoscroll", autoscroll)
	}

You'll see that nothing will be logged. If you add some variable changes like


let st = true
	$: {
		console.log("autoscroll", autoscroll)
		st = !st
	}

you'll see they don't change

Logs

No response

System Info

https://learn.svelte.dev/tutorial/update on Chrome

Severity

Pretty serious bug

ibmua avatar Jun 17 '23 10:06 ibmua

@ibmua I've been able to recreate what you've described in learn.svelte.dev, but after creating this repro repl, I don't think this is a Svelte issue. Could be something about the web containers setup (I'm not really sure). Let me know if the repro accurately reproduces the scenario you've outlined

stordahl avatar Jul 02 '23 22:07 stordahl

I'm not sure I fully understand what the issue here is, but I'm intrigued by this part of the code.

$: {
	console.log({val1, val2, domDep}),
	val2 = !val2
}

If we are updating the value of val2 inside this reactive block, and the block is supposed to run each time val2 changes because we are logging it to the console. Wouldn't this cause (shouldn't this cause) an infinite loop?

MrAmericanMike avatar Oct 26 '23 19:10 MrAmericanMike

No, it doesn't. When a variable changes (marked dirty), the following happens:

  1. looping over each $: block and running the ones that depend on dirtied variables;
  2. running beforeUpdate;
  3. marking all variables as up to date;
  4. updating DOM;
  5. running afterUpdate.

Step 3 prevents infinite loops, plus proper udirting variables individually is too tricky or probably even impossible.

7nik avatar Oct 27 '23 09:10 7nik

Svelte 5 will change the behavior here using the new Runes API. Using $effect and $effect.pre you can listen to the variables you're interested in and it will always refire when they changed. Note that the REPL in the second post would result in an infinite loop right now because it's writing and reading the same value, triggering the effect over and over again. We may look into fixing more obvious cases of this / warn against it so that doesn't happen as easily.

dummdidumm avatar Nov 15 '23 11:11 dummdidumm

I thought about infinite loops cause by self-triggering $effect and came to idea that if your logic cause infinite loops then the logic is wrong and it needs some loop guard or its improvement.

But maybe it would nice to be able to disable $effects' self-triggering though a flag in the second param. Though it may not solve infinite loops over multiple $effects.

7nik avatar Nov 15 '23 12:11 7nik

Closing since this will be addressed in Svelte 5 as pointed out in https://github.com/sveltejs/svelte/issues/8750#issuecomment-1812370086

dummdidumm avatar Feb 08 '24 10:02 dummdidumm