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

Reactive variable not updating as expected when assigned to store value #8211

Closed
Kcwidman opened this issue Jan 19, 2023 · 5 comments
Closed

Comments

@Kcwidman
Copy link

Describe the bug

Reactive variables assigned to the value of a store do not correctly update if the reactive declaration is defined in the code before the store value itself is changed. The store value itself does change, but reactivity is never triggered for any variable reacting to changes in the store value. The strangest thing is that the where the directly reactive statement is defined changes the semantics of the code. Reproducing this bug is very simple, see the attached REPL.

Reproduction

https://svelte.dev/repl/8aecf4ef60f345fcacf6de3880beb7d1?version=3.35.0

Logs

No response

System Info

System:
    OS: Linux 4.18 CentOS Stream 8
    CPU: (16) x64 11th Gen Intel(R) Core(TM) i9-11900K @ 3.50GHz
    Memory: 21.09 GB / 62.44 GB
    Container: Yes
    Shell: 4.4.20 - /bin/bash
  Binaries:
    Node: 18.7.0 - ~/.nvm/versions/node/v18.7.0/bin/node
    npm: 8.15.0 - ~/.nvm/versions/node/v18.7.0/bin/npm
  Browsers:
    Chrome: 109.0.5414.74

Severity

annoyance

@brunnerh
Copy link
Member

brunnerh commented Jan 19, 2023

You break the dependency analysis by using store.set(...) rather than $store = ....

Change

$: s.set(clickCount)

to

$: $s = clickCount

and Svelte will order the statements correctly.

Original compiled update order:

$$self.$$.update = () => {
	if ($$self.$$.dirty & /*$s*/ 1) {
		// defining these two statments are defined before the set statement it results in weird reactivity behavior, but defined at the bottom of this script, it works correctly.
		// try commenting these two lines and uncommenting the corresponding lines below
		$: console.log($s);
	}

	if ($$self.$$.dirty & /*$s*/ 1) {
		$: $$invalidate(1, directReaction = $s);
	}

	if ($$self.$$.dirty & /*clickCount*/ 16) {
		$: s.set(clickCount);
	}
};

After change:

$$self.$$.update = () => {
	if ($$self.$$.dirty & /*clickCount*/ 16) {
		$: set_store_value(s, $s = clickCount, $s);
	}

	if ($$self.$$.dirty & /*$s*/ 1) {
		// defining these two statments are defined before the set statement it results in weird reactivity behavior, but defined at the bottom of this script, it works correctly.
		// try commenting these two lines and uncommenting the corresponding lines below
		$: console.log($s);
	}

	if ($$self.$$.dirty & /*$s*/ 1) {
		$: $$invalidate(1, directReaction = $s);
	}
};

The order can also just manually be fixed in cases where the topological ordering is not possible, so this would work too:

$: s.set(clickCount)
$: directReaction = $s

@Kcwidman
Copy link
Author

Interesting. I would have guessed $s = clickCount is just syntactic sugar for s.set(clickCount). So, is there any reason one should ever use Store.set() vs $store = x? Thanks for the info!

@brunnerh
Copy link
Member

Outside of Svelte files you can't use the special syntax e.g. when implementing custom stores.

@Kcwidman Kcwidman reopened this Mar 21, 2023
@Kcwidman
Copy link
Author

Re-opening this issue because I found an example where your suggestion doesn't solve the issue. Namely, this same behavior isn't fixed by using the $ notation to set a store vs .set. If the $s = someVal occurs inside of a function, this same behavior persists. Is there some other solution/issue with my code? Or is this an issue with svelte reactivity?

https://svelte.dev/repl/461f1b59c3e74177a1dcaa3371933bb8?version=3.57.0

@dummdidumm
Copy link
Member

This comes down to reactive statement ordering + rerun behavior. Svelte 5 will fix this. Closing as duplicate of #6732

@dummdidumm dummdidumm closed this as not planned Won't fix, can't repro, duplicate, stale Nov 15, 2023
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