Skip to main content

Reactivity

DOMY provides a reactive system that allows components to manage state dynamically. This system includes signal, watch, watchEffect, globalWatch, computed, matchPath, and skipReactive to facilitate efficient state management.

signal

The signal function creates a reactive state that updates when its value changes.

Example:

const { signal } = DOMY;
const count = signal(0);

console.log(count.value); // 0
count.value++;
console.log(count.value); // 1

Usage in a Component:

<p>Compteur: {{ count }}</p>
<button @click="count++">+</button>
const count = signal(0);

watch

The watch function observes a specific signal and runs a callback when its value changes.

Example:

const { signal, watch } = DOMY;

const count = signal(0);

watch(
({ prevValue, newValue }) => {
console.log(`Count changed from ${prevValue} to ${newValue}`);
},
() => count
);

watchEffect

The watchEffect function automatically tracks reactive dependencies and runs a callback when any of them change.

Example:

const { signal, watchEffect } = DOMY;

const count = signal(0);

watchEffect(() => {
console.log(`Count updated: ${count.value}`);
});

count.value++; // Logs "Count updated: 1"

globalWatch

The globalWatch function works like watch, but listens all signals. It's really usefull for debugging.

Example:

const { globalWatch } = DOMY;

globalWatch(({ prevValue, newValue }) => {
console.log(`Something changed from ${prevValue} to ${newValue}`);
});

computed

The computed function creates a derived reactive value that updates automatically when its dependencies change.

Example:

const { signal, computed } = DOMY;

const count = signal(0);
const doubleCount = computed(() => count.value * 2);

console.log(doubleCount.value); // 0
count.value++;
console.log(doubleCount.value); // 2

You can also define a setter for this computed:

const { signal, computed } = DOMY;

const count = signal(0);
const doubleCount = computed(
() => count.value * 2,
newValue => (count.value = newValue / 2)
);

console.log(count.value); // 0
doubleCount.value = 2;
console.log(doubleCount.value); // 2
console.log(count.value); // 1

matchPath

When managing reactive state, monitoring every change in a complex object can be inefficient. matchPath helps filter updates dynamically, executing logic only when relevant parts of the state are modified.

Example:

const { signal, watch, matchPath } = DOMY;

const state = signal({
todos: [{ isComplete: false }, { isComplete: true }]
});

// Watching for changes in todos using matchPath
watch(
({ prevValue, newValue, path }) => {
if (matchPath('todos.*.isComplete', path).isMatching) {
console.log(`Updated path: ${path}, New Value: ${newValue}`);
}
},
() => state
);

It also allow to get the params from a path:

const { signal, watch, matchPath } = DOMY;

const state = signal({
todos: [{ isComplete: false }, { isComplete: true }]
});

// Watching for changes in todos using matchPath
watch(
({ prevValue, newValue, path }) => {
const matcher = matchPath('todos.{index}.isComplete', path);
if (matcher.isMatching) {
console.log(`Updated path: ${path}, New Value: ${newValue}, Index: ${matcher.params.index}`);
}
},
() => state
);

skipReactive

The skipReactive function allows you to skip tracking reactive properties, preventing unnecessary updates.

Example:

const { signal, skipReactive } = DOMY;

// In the example below, DOMY won't listen to any change make on roles
const user = signal({ name: 'Alice', roles: skipReactive(['admin']) });