Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

$effect deep call & $effect untrack (docs, feature) #14238

Closed
dm-de opened this issue Nov 10, 2024 · 3 comments
Closed

$effect deep call & $effect untrack (docs, feature) #14238

dm-de opened this issue Nov 10, 2024 · 3 comments

Comments

@dm-de
Copy link

dm-de commented Nov 10, 2024

Describe the problem

High frustration with $effect and deep function calls.

Is this really, how it was designed?

Recommendation: Add new rune like $effect.deep() - if this is necessary in very rare cases.

Default $effect should not go beyound 1st level.

This deep behavior is not correct documented in docs:

https://svelte.dev/docs/svelte/$effect
$effect automatically picks up any reactive values ($state, $derived, $props) that are synchronously read inside its function body and registers them as dependencies. When those dependencies change, the $effect schedules a rerun.

<script>
	let count = $state(0)
	
	$effect(() => deep())

	function deep() {
		deeper()		
	}

	function deeper() {
		count = count + 1
		//here is no limit, how deep tracking can go
		//Error: effect_update_depth_exceeded Maximum update depth exceeded.:
	}
</script>

{count}

Another high frustration level with $effect.
It took me 1h to find the problem.

<script>
	import {untrack} from 'svelte'
	let nav = $state()
	
	$effect(() => {
		nav = []
		//nav.push('a') //<<< endless loop
		//untrack(() => nav).push('a') //<<< endless loop
		untrack(() => nav.push('a')) //ok
	})
</script>

I did not expect a "read" with nav.push() - on second view this was clear.
But I did not expect a "read" with untracked nav
How can this happen, if nav is already untracked?
Only untracking whole nav.push() runs well.
This behavior should also be documented

Recommendation:: Add untrackAll() - which will disable any tracking "reads" - so you don't need to write untrack all the time, if you call push for example.

	$effect(() => {
		untrackAll(nav, morevariables...)
		nav = []
		nav.push('a')
		nav.push('b')
		nav.push('c') //don't need untrack all the time
	})

or opposite to react: a non-tracking array (optional):

	$effect(() => {
		nav = []
		nav.push('a')
		nav.push('b')
		nav.push('c')
	}, [nav, morevariables...])

Describe the proposed solution

see above

Importance

would make my life easier

@brunnerh
Copy link
Member

brunnerh commented Nov 10, 2024

  • Changing how $effect works would be a breaking change, so I doubt that is going to happen.
    It also makes the behavior harder to understand and introduces an inconsistency you have to know about to not make mistakes.
    Refactorings are likely to break code if additional indirection is added somewhere.
  • untrack operates on executed logic, not variables. You also don't have to call it multiple times if you just want to untrack an entire section of code.
    $effect(() => {
      nav = []
      untrack(() => {
        nav.push('a')
        nav.push('b')
        nav.push('c')
      });
    });
    (push causes loops because it reads to length of the array internally.)

@paoloricciuti
Copy link
Member

  • Changing how $effect works would be a breaking change, so I doubt that is going to happen.
    It also makes the behavior harder to understand and introduces an inconsistency you have to know about to not make mistakes.
    Refactorings are likely to break code if additional indirection is added somewhere.

  • untrack operates on executed logic, not variables. You also don't have to call it multiple times if you just want to untrack an entire section of code.

    $effect(() => {
      nav = []
      untrack(() => {
        nav.push('a')
        nav.push('b')
        nav.push('c')
      });
    });

    (push causes loops because it reads to length of the array internally.)

What @brunnerh said is spot on...I understand you are used to the old labeled statement but and this is a shift from how it worked but it's just a matter of getting used to think this way. Therefore closing, but thanks for reporting 😌

@paoloricciuti paoloricciuti closed this as not planned Won't fix, can't repro, duplicate, stale Nov 10, 2024
@paoloricciuti
Copy link
Member

But I'll update the documentation to be more clear

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants