-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Svelte 5: Make untrack a rune #9451
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
Comments
I suspect that $effect(() => {
// <reactive>
untrack(() => {
// <unreactive>
});
}); |
Yeah that makes sense. I guess I didn't consider that |
I'm going to reopen this to see how others feel about this. We're not entirely sure yet ourselves if we want to make it a rune or not. |
Without expressing an opinion on this particular issue, I will say that our current philosophy of only making things runes if they absolutely have to be perhaps can be difficult to approach from a user-perspective because it requires a very high degree of knowledge to know whether something would be a rune or not. |
From the preview site docs:
I think that should not define whether something should be a rune or not. Runes is more of a marketing term and it should be so. It makes more sense to me to make it a rune as it purely exists for usage inside |
Another argument of making it a rune: By the logic of "only make things a rune that absolutely have to", |
Hello, Just my two-cents. IMHO the rune is more logical (and more concise) when accessing a state/prop.
And, we should use two syntax :
|
Also, not sure if I should post here or create another issue, but I think that untrack should handle proxified object/array. For example image this : let array = $state([ ... ]);
let value = $state('val');
$effect(() => {
const a = untrack(() => array);
console.log("array length: " + a.length);
console.log("includes value: " + a.includes(value));
}); Here $effect(() => {
console.log("array length: " + untrack(() => array.length));
console.log("includes value: " + untrack(() => array.includes(value)));
value; // needed to track value, because of untrack
}); I think that this line |
With automatic dependencies, I don't see any interest of explicit dependencies. It's a regression. I don't want explicit dependencies, just a simplier way to untrack some states/props... |
I hope the philosophy has since shifted further away from this towards creating a more consistent developer experience. |
It happened to me a couple times that I needed to manually control which variables triggered reactivity, and in all those cases it was easier for me to specify which variables to track, and not which ones to untrack. I just created a function receiving only the variables I want to track, even though inside the function I might access other top-level (and thus reactive) variables. It seems to me like that would be the most common scenario. So I think something like #9248 would be very useful indeed. |
One major benefit of a For me the problem with In this way |
Tbf onMount, on destroy, before/after/onNavigate are all first-class framework features that have to be imported |
@eddiemcconkie As a user I would want to have The point is it interrupts the flow in userland to have to think about which functionality needs to be imported, and that it is really only beneficial to the library author to know the distinction between compiler-only functions. |
Something I am unsure of, is if there are people using Otherwise since you've already started down this path with Does anyone remember classes autoload in PHP? I actually find it much nicer when you have a subset of known functionality that you want to tap into to not have to junk up files in the same project space with includes... |
If we slightly modify that definition: https://svelte-5-preview.vercel.app/docs/runes
Then for a
|
Looking at the preview docs, before/afterUpdate are getting deprecated. I believe onMount is sticking around. You can use an effect to do the same thing as onMount, but you'd need to untrack any reactive state manually if you just want to run something once when the component mounts, so I think onMount is still more convenient in some cases. onNavigate is useful for view transitions.
Honestly this isn't much of a concern when your text editor does auto imports. Originally I thought untrack would be better as a rune, but I do think what the Svelte team said about only making things runes when necessary makes a lot of sense and I can get on board with that. |
@eddiemcconkie I respect that, but whole-heartedly disagree. You mentioning the IDE auto-import is rather ironic considering how that's a poor man's version of what I think would be the more robust option. |
Svelte exports more than just lifecycle functions. There are also things like stores or transition functions. Explicit imports help avoid naming collisions. It probably also makes it much easier for the Svelte team since they can just write and export plain JavaScript and not have to worry about making everything globally available |
@eddiemcconkie For the no-compiler-required functions I would imagine they would still just do the import for use behind the scenes. If this is the strategy I'm not sure there is much of a scope issue outside of having to document and stub out more "runes". As long as runes a prefixed with I'm not too familiar with it but with tree-shaking isn't it also a non issue if they just put everything on a global You specifically called out transitions, isn't that already it's own module? https://svelte.dev/docs/svelte-transition Not like EDIT: For reference, here is all the modules in svelte: https://github.com/sveltejs/svelte/tree/main/packages/svelte/src I'm thinking it wouldn't be too crazy to have all these be |
I've only ever used SvelteKit, not svelte alone. Didn't think about it when you mentioned However if we ask "Is it function-like?" Answer: Yes. "Do you HAVE to import them from somewhere?" Answer: It's core functionality in Kit. "Is it part of the language?" Answer: It's part of the "language" of Kit. So, if we were to follow the modified definition of what we call a You are right about
Regarding my modified idea of what a
I understand that I am more or less hijacking the original intention of runes here to mean something that you would otherwise from svelte (or kit). You probably ascribe lower level meaning to I hope you can see that now because 5 is being a more expressive than the previously transparently overriding In fact, as a user, I want and expect this. But, as a framework author I understand you may value the original intention more than what users expect, and they will just have to learn that some very specific parts are compiled out (the current runes), but not all parts. The unfamiliar user will not know why this is the case, and may expect what I am saying here because they don't really care to know the reason why the first Ultimately I will use Svelte either way, I just foresee a lot of users being confused by the difference in usage pattern between runes and other "parts of the language" provided by svelte/kit, and not really caring why it is different, and instead just wanting one consistent pattern if they could. My thoughts are that only contributors and framework authors are going to want to understand the difference between Essentially the whole import difference makes me want to have A lot of words, I but I THINK I have a point. May be wrong though. EIDT: Just to get back to where this all started with This feels a lot more natural: <script>
let size = $state(50);
let color = $state('#ff3e00');
let canvas;
$effect(() => {
const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
// this will re-run whenever `color` or `size` change
context.fillStyle = color;
$untrack(() => {
context.fillRect(0, 0, size, size);
})
});
</script> Than this: <script>
import { untrack } from 'svelte';
let size = $state(50); // Just doesn't feel right to have magic here...
let color = $state('#ff3e00');
let canvas;
$effect(() => {
const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
// this will re-run whenever `color` or `size` change
context.fillStyle = color;
untrack(() => { // But not any magic here...
context.fillRect(0, 0, size, size);
})
});
</script> I feel it is not important for users to understand why |
Feel free to mark my comments as off-topic. Prolly should have started a different thread. Just thought it sounded like a plausible idea to put everything svelte-related behind |
Untracking a value and untracking a block of code are two very different things. It feels quite weird that the current IMO, the api should have:
|
I wonder if this still holds true? I know these docs are subject-to-change but. I don't see Also from this page: https://svelte-5-preview.vercel.app/docs/runes I think
Also for me, I wonder why If I wanted to run something strictly "on mount", (e.g. a useEffect without deps), then I would use |
onMount won't be deprecated. It will just be shipped as |
We decided against making |
Describe the problem
The
untrack
function feels a little clunky to use since you have to pass it a function instead of a value. I think it could be easier to use if you could just give it an expression.Describe the proposed solution
Would it make sense to swap the
untrack
function for an$untrack
rune?The preview docs for $derived says:
and I think it makes sense to enforce the same behavior when untracking reactive variables to avoid side-effects. I feel like
$untrack(count)
is a bit easier to read thanuntrack(() => count)
. It would also be nice that you wouldn't have toimport { untrack } from 'svelte'
.Alternatives considered
N/A
Importance
nice to have
The text was updated successfully, but these errors were encountered: