Saltearse al contenido

Gestor de estados

La gestión de estados es un aspecto crítico de cualquier aplicación, ya que es la encargada de controlar y mantener la coherencia de los datos a lo largo del tiempo. Facilita la actualización y el seguimiento de los cambios en el estado, asegurando una experiencia de usuario fluida y un funcionamiento estable de la aplicación.

En Reactter sabemos la importancia de la gestión de estados, por lo que hemos diseñado un sistema de gestión de estados que es eficiente, reactivo y fácil de usar.

A continuación, te mostramos los mecanimos que Reactter ofrece para la gestión de estados y aprenderás cómo funcionan.

API

Reactter proporciona una gran variedad de mecanismos para la gestión de estados, incluyendo clases, hooks y métodos:

¿Cómo funciona?

El sistema de gestión de estados de Reactter se basa en el concepto de reactividad. Contrario a la noción predominante de que implementar programación reactiva en Dart puede ser desafiante, Reactter simplifica en gran medida este proceso. Para adentrarnos en el concepto, comencemos explorando qué constituye un estado en Reactter.

Estado

Todos los estados en Reactter son clases que heredan de RtState , la cual encapsula los datos y el comportamiento de un estado particular, y proporciona una forma de notificar a los observadores cuando el estado cambia

Metodos del estado

La clase RtState proporciona algunos métodos para la gestión de estados. Conozcámoslos:

  • update : Ejecuta una función callback y notifica a sus observadores que el estado ha cambiado. Cuando se invoca, emite dos eventos lifecycle para señalar la transición de estado:
    • Lifecycle.willUpdate se emite primero, indicando la actualización inminente.
    • Lifecycle.didUpdate se emite una vez que el proceso de actualización se ha completado.
  • notify : Fuerza al estado a notificar a sus observadores. A diferencia de update , sólo emite el evento Lifecycle.didUpdate, ya que no implica ningún paso previo a la notificación.
  • bind : Establece una conexión entre el estado y una instancia específica. Esta conexión permite a la instancia actualizarse de forma reactiva en función de los cambios en el estado. Al vincular el estado, la instancia es notificado de los cambios en el estado y puede reflejar adecuadamente esos cambios en su comportamiento.
  • unbind : Libera la conexión entre el estado y la instancia. Al desvincularse, la instancia dejará de recibir actualizaciones del estado. Esto puede ser útil cuando una instancia ya no está utilizando activamente el estado o cuando necesita desvincularse del estado temporal o permanentemente.
  • dispose : Es responsable de limpiar el estado y cualquier observador o recurso asociado. Disponer del estado garantiza que se libere correctamente y que ya no consuma memoria o recursos de procesamiento innecesariamente.

Ejemplo

Veamos un ejemplo de una cuenta regresiva utilizando Signal y desentrañaremos lo qué sucede bajo el capó.

main.dart
1
import 'dart:async';
2
import 'package:reactter/reactter.dart';
3
4
// Crea un estado reactivo llamado `count` utilizando la clase `Signal`
5
final count = Signal(10);
6
7
void main() async {
8
// Escucha el evento `didUpdate` del estado `count`
9
// e imprime `value` de `count` con cada actualización
10
Rt.on(
11
count,
12
Lifecycle.didUpdate,
13
(_, __) => print('Count: $count'),
14
);
15
16
// Crea un temporizador que invoca la función `countdown` cada segundo
17
await Timer.periodic(Duration(seconds: 1), countdown);
18
}
19
20
// Decrementa `value` de `count` en 1 cada ciclo del temporizador
21
// y cancela el `timer` cuando `value` de `count` llegue a 0
22
void countdown(Timer timer) {
23
count.value -= 1;
24
25
if (count.value == 0) {
26
timer.cancel();
27
}
28
}

Ahora veamos que contiene la clase Signal y cómo se actualiza el estado count en el ejemplo anterior

signal.dart
1
class Signal<T> with RtState {
2
// Valor del estado
3
T _value;
4
5
// Constructor privada, solo se puede crear una instancia de `Signal` a través del factory.
6
Signal._(this._value);
7
8
factory Signal(T value) {
9
// Se registra un nuevo estado en el contexto de Reactter
10
return Rt.registerState(
11
() => Signal._(value),
12
);
13
}
14
15
T get value => _value;
16
17
set value(T val) {
18
if (_value == val) return;
19
20
// Notifica a los oyentes que el estado ha cambiado,
21
// disparando los eventos `Lifecycle.willUpdate` y `Lifecycle.didUpdate` en orden.
22
update((_) => _value = val);
23
}
24
25
[...]
26
}

Durante el proceso, a medida que el value de count cambia, se desencadena el evento Lifecycle.didUpdate, el cual es disparado por el método update (signal.dart, linea 22). Este evento es escuchado por el método Rt.on (main.dart, linea 10), que imprime el value de count.

Esto ocurre gracias a la reactividad de Reactter, que es encargada de notificar a los oyentes mediante la emisión de eventos relacionados con el ciclo de vida del estado.