-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Allow $effect.pre to run on the server #9278
Comments
The recommended way to do this currently is to put |
One idea from 7nik on Discord:
|
Rich hit this very issue (or rather, a problem that would've been solved if I second that "Why doesn't |
Can someone give me an example of work you'd want to do in an The replacement for |
The livestream example is a great And even though it can be fixed by turning spring and tweened into utilities that return reactive values, many third-party solutions (like tanstack query) make use of stores or the store contract Another good reason is the reactive use of context (also used in tanstack query) which cannot be used within $derived as it needs to be executed during component initialization I also tried migrating the beforeUpdate example from the tutorial to runes and it only works with $effect.pre, it doesn't work with $derived, not sure if it's a bug |
If you're referring to the autoscroll example, it's not a great example to begin with: #9248 (comment)
This is somewhere you'd use |
The scroll example is not a good example because the state is only modified in one place, it is very simple to move the side effect logic into the event handler But if a state is modified in several places it doesn't make sense to add the "side effect" in all of them Having a point where you can react to state changes indiscriminately is a much more common use of effect than a point where it is safe to reference the DOM or perform cleanups Even React recommends running side effects during render to react to a state change when an event handler is not possible/practical and waiting for the DOM would be unnecessary/harmful, $effect.pre is the closest equivalent to that
|
As I said some 3rd party libraries use the context internally, manually retrieving the context in a separate location is unfortunately not always an option, which is why $effect.pre is more ideal |
In Svelte Flow you can pass a lot of configuration options as props to our main component. To prevent prop drilling and for architectural reasons (interactive flow graphs cannot be solved with simple top-to-bottom state flow), we are syncing these props to an internal store. Before, we could just do the good ol' $: syncState(some, props) Now, to fix SSR (and hydration mismatches) we have to do: syncState(some, props) // initial run on server
$effect.pre(() => { syncState(some, props) }); This is not ideal because it will initially run twice on the client. (Not too bad, but also not very good...) To make the Bottom line: This issue is not a showstopper at all but things would be simpler if effect.pre would just run on the server. P.S. |
Having worked around this issue quite a bit more, I would like to double down on it. I'd argue that
let useless = $derived.by(() => { syncToGlobalState(some, props); });
useless; // needed, so the compiler does not throw it away
Again, this is an edge case. I can live with these complications for the greater good and keeping things simple, however I am pretty sure this issue will arise for any library maintainers requiring some kind of global state. I welcome any solutions, of course, maybe there is a possibility I haven't found yet. |
|
One use case is building prerendered static pages with I'd be happy if any of the following resulted with
I was quite surprised when none of the above had any effect with CSR disabled. |
Obviously, the first option can work only in the browser environment and only proves that Basically, your issue is #3105 and related ones. And the workaround is probably still transformPage. |
Describe the problem
A common practice when using SvelteKit is to use reactive expressions for expressions that need to be executed reactively on the client but also need to be executed non-reactively on the server during ssr
Svelte 5 will bring the $effect and $effect.pre runes to replace reactive expressions, but with the difference that these runes will not be executed on the server, creating the need to repeat code to achieve the same behavior
// before $: { // really big expression }
Describe the proposed solution
The reason the $effect rune does not run on the server is because it runs after the DOM is mounted, but the $effect.pre rune does not need to wait for the DOM, and is therefore ideal for reproducing the behavior of reactive expressions
Just as the $state and $derived runes are transformed into common variables during SSR, the $effect.pre rune can be transformed into a simple IIFE
Alternatives considered
Manually transform the expression into a function, but this requires changing the code design and still requires duplicate execution with environment checking
Importance
would make my life easier
The text was updated successfully, but these errors were encountered: