An Interest In:
Web News this Week
- March 20, 2024
- March 19, 2024
- March 18, 2024
- March 17, 2024
- March 16, 2024
- March 15, 2024
- March 14, 2024
"Deep" reactivity in Svelte
From the Vue.js documentation:
The reactive conversion is "deep": it affects all nested properties.
In Vue.js, when using the data option or the reactive() function, a JavaScript object is transformed into an object where each individual property (including those on nested objects) is reactive. Each property in effect becomes its own "store".
In Svelte, there is no way to make object properties reactive like that. Reactivity is only available for local variables declared at the root level of each component.
A reactive "store" from outside the component, must first be assigned to a local variable, and then the store value can be accessed/assigned using a "$" prefix on the local variable.
Most of the time, the Svelte's reactivity model is entirely sufficient and very easy to use.
However, if you need to synchronize a large/complex JavaScript object between multiple Svelte components, views, etc. the Vue model is much more convenient.
To "fix" this, I came up with a tiny helper library "ReactivePojo", which lets you map a local variable in a Svelte component, to a property on any POJO (Plain Old JavaScript object) - via a custom reactive store (honoring the Svelte store contract) - like this:
let v = RPStore(object, propertyName);
The property value can then be accessed/assigned using the "$" prefix:
console.log($v);$v = "New value";
Calling RPStore
will create a store for the specified object/property - unless one already exists, in which case the existing store is returned. In other words - any call to RPStore
for the same object and property name, from anywhere, will always return the same store.
This ensures that two separate Svelte components accessing the same object/property will get the same store and thus the property value will automatically be synchronized between the components (and the underlying object).
An RPSet
helper method is also provided, allowing you to assign a value to a property triggering reactivity if that property is connected to a store:
RPSet(object, propertyName, newValue)
The difference between that and RPStore(object, propertyName).set(newValue)
, is (besides from the shorter syntax) that RPSet
will NOT create a new store behind the scenes if one does not already exist. Instead it will simply assign the value directly (since no one is listening for changes anyway).
As long as a property value is only assigned through a RPStore
store or the RPSet
method, everything will be kept perfectly in sync. Assigning a new value directly to the property will not be "seen" and will not trigger reactivity.
Reactive UI updates will also only happen when accessing the property via the store (using the $variable
syntax).
To use this library in a Svelte component:
<script>import {RPStore, RPSet} from "./ReactivePojo.js";import {Person} from "./MyGlobalData.js"; // Note: "Person" object could also come from a property, GetContext(...), etc.let Name = RPStore(Person, "Name");</script>Name: <input type="text" bind:value={$Name} />
This solution won't give you all the same conveniences that Vue's deep conversion does, but it does give you reactivity at a more granular level (like with Vue) - preventing re-calculations/re-rendering based on the entire object when the value of some leaf node property changes.
And it kind of magically makes a POJO reactive.
"ReactivePojo" is available at https://github.com/jesperhoy/Svelte-ReactivePojo
Original Link: https://dev.to/jesperhoy/deep-reactivity-in-svelte-4h4c
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To