svelte-autotracking v0.2.0
Svelte Autotracking
A library to automatically track changes on Svelte stores with decorators.
It's freely inspired by the @tracked decorator from Ember.js, and it's meant to be used with Svelte stores.
If you're using Svelte stores, you know that you need create complex logic (like derived stores and custom store) to track changes on your components. Even the simplest of them.
This library aims to simplify this process by providing a set of decorators and helpers that you can use to :
- automatically track changes on your object logic
- and automaticaly create stores to be cosumed by your components.
You have just to concentrate on your logic, create your objects and let the library handle the rest.
Example
You can create a class with autotracking capabilities by extending the Autotracking class and using the @tracked decorator on the properties you want to track.
import { Autotracking, tracked } from "svelte-autotracking";
/**
* Counter class with autotracking capabilities.
*/
export class Counter extends Autotracking {
@tracked
_count = 0;
get count() {
return this._count;
}
increment() {
this._count += 1;
}
decrement() {
this._count -= 1;
}
}And then, you can use it in your Svelte components like this:
<script>
import { Counter } from "./Counter.js";
import { useStore } from "svelte-autotracking";
const counter = useStore(new Counter());
</script>
<h1>{$counter.count}</h1>
<button on:click={() => $counter.increment()}>+</button>
<button on:click={() => $counter.decrement()}>-</button>So, when you click on the buttons, the count property will be automatically updated and the component will re-render. And even if you create a derived class from the Counter.
Installation
npm install svelte-autotrackingor
yarn add svelte-autotrackingRequirements : Decorators
This library uses the decorators feature of JavaScript, which is currently a stage 2 proposal. So, you need to enable it in your project.
If you're using TypeScript, you can enable it by adding the following configuration to your tsconfig.json file:
{
"compilerOptions": {
"experimentalDecorators": true,
"target": "ES6" // or higher
}
}If you're using Babel, you can enable it by installing the @babel/plugin-proposal-decorators plugin:
npm install --save-dev @babel/plugin-proposal-decoratorsAnd then, add it to your Babel configuration:
{
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }]
]
}How to use this library
Autotracking class
You can create a class with autotracking capabilities by extending the Autotracking class.
import { Autotracking } from "svelte-autotracking";
class MyClass extends Autotracking {
// your code here
}@tracked decorator
You can use the @tracked decorator to automatically track changes on the properties of your class.
import { Autotracking, tracked } from "svelte-autotracking";
export class MyClass extends Autotracking {
@tracked
property = "value";
method(newValue: string) {
this.property = newValue;
}
}So, when you change the property value, the component will re-render. even :
- if you change the value directly
- if you change the value in a method (like
methodin the example above) - if you change the value in a nested object
- if you derive a new class from
MyClass
useStore function
You can use the useStore function to create a store from an instance of a class with autotracking capabilities.
import { MyClass } from "./MyClass.js";
const myClass = new MyClass();
const store = useStore(myClass);And then, you can use the store in your Svelte components like this:
<script>
import { MyClass } from "./MyClass.js";
import { useStore } from "svelte-autotracking";
const myClass = new MyClass();
const store = useStore(myClass);
</script>
<h1>{$store.property}</h1>
<button on:click={() => $store.property = "new value"}>Change value</button>
<button on:click={() => $store.method("another new value")}>Change value by method</button>So, when you click on the buttons, the property value will be automatically updated and the component will re-render.
Add capabilities to an existing class
You can add autotracking capabilities to class by using the Autotracked decorator.
import { Autotracked, tracked, type IAutotrackable } from "svelte-autotracking";
@Autotracked
export class MyClass {
@tracked
property = "value";
method(newValue: string) {
this.property = newValue;
}
}
interface MyClass extends IAutotrackable<Named> { }In this example, the MyClass class will have autotracking capabilities, and you can use it in your Svelte components.
⚠️ Don't forget to add the
IAutotrackableinterface to the class. The@Autotrackeddecorator is a class decorator that adds the autotracking capabilities to the class. And theIAutotrackableinterface is a generic interface that extends theIAutotrackableinterface with the properties of the class. Without it, in the component, you will not have class features recognition.
use the @tracked decorator in a nested object
Sometimes, you may want to track changes on a nested object. You can do this by using the @tracked decorator on the properties of the nested object and declaring the nested object as autotrackable but by using its parent class.
import { Autotracking, AutotrackingFromStore, tracked, type IAutotrackable } from 'svelte-autotracking';
export class Owner extends Autotracking {
nested: Nested;
constructor() {
super();
this.nested = new Nested(this);
}
}
interface INested extends IAutotrackable<Owner> {
owner: Owner;
}
export default class Nested extends AutotrackingFromStore(
// function to get the owner that brings the autotracking capabilities
function (this: INested) { return this.owner; }
) implements INested {
owner: Owner;
@tracked
count = 0;
constructor(owner: Owner) {
super();
this.owner = owner;
}
increment() {
this.count++;
}
decrement() {
this.count--;
}
}In this example, the Nested class is a nested object of the Owner class. And the Owner class is the parent class of the Nested class. So, you can use the @tracked decorator on the properties of the Nested class and declare the Nested class as autotrackable by using the IAutotrackable interface with the Owner class.
And then, you can use the Nested class in your Svelte components like this:
<script>
import { Owner } from "./Owner.js";
import { useStore } from "svelte-autotracking";
const owner = useStore(new Owner());
const nested = owner.nested;
</script>
<h1>{$nested.count}</h1>
or
<h1>{$owner.nested.count}</h1>
<button on:click={() => $nested.increment()}>+</button>
<button on:click={() => $nested.decrement()}>-</button>Trigger a manual update
You can trigger a manual update by calling the triggerUpdate method the autotracked object.
import { triggerUpdate } from "svelte-autotracking";
import { MyClass } from "./MyClass.js";
const myClass = new MyClass();
// trigger a manual update
triggerUpdate(myClass);Use the @updateAfter decorator
You can use the @updateAfter decorator to automatically update the store when a method is called event if no property is decorated with @tracked.
import { Autotracking, tracked, updateAfter } from "svelte-autotracking";
export class MyClass extends Autotracking {
property = "value";
@updateAfter
method(newValue: string) {
this.property = newValue;
}
}In this example, the method method will automatically update the store when it's called, even if the property property is not decorated with @tracked. So, in a Svelte component, when you call the method method, the component will re-render.
Silent change value without triggering an update
You can change the value of a property without triggering an update by using the silentSet function.
import { silentSet } from "svelte-autotracking";
const myClass = new MyClass();
// change the value without triggering an update
silentSet(myClass, "property", "new value");Explanation
The @tracked decorator is a property decorator that automatically tracks changes on the property of a class. When you change the value of the property, the component will re-render.
Autotracking automatically adds a writable store and @tracked decorator add a call to the update function of the store when the property is changed. that's all.
Author
See AUTHORS.md for more information.
License
This project is licensed under the MIT License. See LICENSE.md for details.
©2024 Emmanuel FITOUSSI