-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
feat: $state.eager(value)
#16849
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
base: main
Are you sure you want to change the base?
feat: $state.eager(value)
#16849
Conversation
|
|
The problem with only being able to use it in the template is that you need to be vigilant about using it in all places your state shown if you want to avoid tearing of displays of the same state |
yeah it 100% must be usable in the script tag aswell (e.g. inside $derived) |
People have doubts about the name. So do I. I reused So what should we rename it, and should we also rename |
I'm thinking of |
|
I encountered a similar problem. Should this be moved to a separate issue? iShot_2025-09-30_10.14.18.mp4 |
* runtime-first approach * revert these * type safety, lint * fix: better input cursor restoration for `bind:value` (#16925) If cursor was at end and new input is longer, move cursor to new end No test because not possible to reproduce using our test setup. Follow-up to #14649, helps with #16577 * Version Packages (#16920) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * docs: await no longer need pending (#16900) * docs: link to custom renderer issue in Svelte Native discussion (#16896) * fix code block (#16937) Updated code block syntax from Svelte to JavaScript for clarity. * fix: unset context on stale promises (#16935) * fix: unset context on stale promises When a stale promise is rejected in `async_derived`, and the promise eventually resolves, `d.resolve` will be noop and `d.promise.then(handler, ...)` will never run. That in turns means any restored context (via `(await save(..))()`) will never be unset. We have to handle this case and unset the context to prevent errors such as false-positive state mutation errors * fix: unset context on stale promises (slightly different approach) (#16936) * slightly different approach to #16935 * move unset_context call * get rid of logs --------- Co-authored-by: Rich Harris <[email protected]> * fix: svg `radialGradient` `fr` attribute missing in types (#16943) * fix(svg radialGradient): fr attribute missing in types * chore: add changeset * Version Packages (#16940) * Version Packages * Update packages/svelte/CHANGELOG.md --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Rich Harris <[email protected]> * chore: simplify `batch.apply()` (#16945) * chore: simplify `batch.apply()` * belt and braces * note to self * unused * fix: don't rerun async effects unnecessarily (#16944) Since #16866, when an async effect runs multiple times, we rebase older batches and rerun those effects. This can have unintended consequences: In a case where an async effect only depends on a single source, and that single source was updated in a later batch, we know that we don't need to / should not rerun the older batch. This PR makes it so: We collect all the sources of older batches that are not part of the current batch that just committed, and then only mark those async effects as dirty which depend on one of those other sources. Fixes the bug I noticed while working on #16935 * fix: ensure map iteration order is correct (#16947) quick follow-up to #16944 Resetting a map entry does not change its position in the map when iterating. We need to make sure that reset makes that batch jump "to the front" for the "reject all stale batches" logic below. Edge case for which I can't come up with a test case but it _is_ a possibility. * feat: add `createContext` utility for type-safe context (#16948) * feat: add `createContext` utility for type-safe context * regenerate * Version Packages (#16946) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * chore: Remove annoying sync-async warning (#16949) * fix * use `$state.eager(value)` instead of `$effect.pending(value)` --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Hyunbin Seo <[email protected]> Co-authored-by: Ben McCann <[email protected]> Co-authored-by: Rich Harris <[email protected]> Co-authored-by: Hannes Rüger <[email protected]> Co-authored-by: Elliott Johnson <[email protected]>
Fixed the first thing, opened #16954 for the second as I think it's a manifestation of a pre-existing bug and shouldn't prevent us from shipping this |
The
$effect.pending
rune tells you how manyawait
expressions are unresolved in the current boundary, which is useful for providing feedback to the user that something is happening.This PR adds a
$state.eager(value)
rune that also updates immediately, regardless of whether the rest of the UI is suspending while async work happens. A bit like React's useOptimistic except much less confusing and you can use it with state you don't 'own' (and without having to pass an optimistic version of that state around).Quick primer: when a piece of state changes, and an
await
expression depends on that state, Svelte doesn't update the UI to reflect the state change until theawait
expression has resolved. Otherwise it's a total free-for-all — if you have one component that doesawait fetchPost(params.slug)
and another one that doesawait fetchComments(params.slug)
, the post and the comments will be rendered at different times. Or, to take a contrived example that makes it clear, in a case like this......if
n
changes from1
to2
the UI will show1 * 2 = 1
. This is a bad default.Other frameworks solve this with things like useTransition. Svelte's view is that you want to use a transition in 99% of cases, and so making it opt-in rather than opt-out is the wrong choice. But right now we don't have an opt-out mechanism.
$state.eager(...)
is that mechanism. It allows you to always show the latest version in one specific part of your UI — for example, in the button that changes some state.Caveats:
Before submitting the PR, please make sure you do the following
feat:
,fix:
,chore:
, ordocs:
.packages/svelte/src
, add a changeset (npx changeset
).Tests and linting
pnpm test
and lint the project withpnpm lint