Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
February 17, 2022 03:35 pm GMT

"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

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To