Skip to content

Runes: Cannot pass single value state around / migrating simple stores #9252

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

Closed
brunnerh opened this issue Sep 23, 2023 · 6 comments
Closed
Labels

Comments

@brunnerh
Copy link
Member

brunnerh commented Sep 23, 2023

Describe the bug

Since $state currently requires an object to to not lose reactivity, it does not seem possible to just pass a single reactive value around without wrapping it.

If runes are supposed to be able to replace stores (as pointed out here), this seems like a significant flaw.

Rather than having $store everywhere, it would be something like state.value, but unlike $ the property could be called anything; it is more verbose and less stable.

Reproduction

function someExtractedLogic() {
  let state = $state();
  // ...
  return state; // Will not be reactive
}

Logs

No response

System Info

[Svelte 5 preview]

Severity

annoyance

@stalkerg
Copy link
Contributor

stalkerg commented Sep 25, 2023

even more, send state from component will not work!

<script>
	import { setStore, increment } from './test.js';
	
	let s = $state(0);
	setStore(s);
</script>

<button on:click={increment}>Hello {s}</button>
<button on:click={() => s += 1}>Hello2 {s}</button>

// test.js
let myStore;

export function setStore(store) {
	myStore = store;
}

export function increment() {
	myStore += 1;
	console.log(myStore);
}

First button will not work but the second will. With store, it's working fine.

@7nik
Copy link
Contributor

7nik commented Sep 30, 2023

From what I got after playing with runes a bit, the reactive gets lost after reading a reactive variable (or passing it somewhere). This simplifies understanding of what is reactive and prevents the "leaking" of reactivity. But as a result, we must use set/get to pass reactivity. For the same reason, the reactivity doesn't work in loops.

There are legit cases to keep reactivity while passing a value somewhere. On the other hand, it will be tricky to understand what is reactive and what isn't.

@stalkerg, thus you need to use there $effect(() => setStore(s));

@JakeBeaver
Copy link
Contributor

We definitely need a helper like $box, seeing as wrapping a state with a get/set object is a very common usecase. Even if we don't see a $unbox or $state.from, dealing with the dangling .value is much less painful than needing to create a bespoke object definition for each exported state.

Unless I'm missing a way to implement that helper myself in user land, in which case please help :D

@brunnerh
Copy link
Member Author

brunnerh commented Mar 3, 2024

Creating a new boxed state is as simple as:

let boxed = $state({ value: ... });

To transfer an existing reactive value you need to define a getter/setter around it, the best you probably could currently do in terms of simplicity would be to have a function that delegates a tiny bit.

- let boxed = $box(value);
+ let boxed = box(() => value, v => value = v);
function box(get, set) {
  return {
    get value() { return get(); },
    set value(v) { set(v); },
  };
}

REPL

@JakeBeaver
Copy link
Contributor

Thanks, that's actually exactly as far as I got with simplifying it myself, very nice to validate that this probably is the best possible thing with the current functionality.

That lowering of $box(x) to box(get, set) (or even to the full object declaration) is something I'd most likely end up writing a preprocessor for myself, but it would be super nice if it was a part of the default experience

@Rich-Harris
Copy link
Member

Closing for the reasons given in #9237 (comment)

@Rich-Harris Rich-Harris closed this as not planned Won't fix, can't repro, duplicate, stale Apr 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants