Skip to content

State Management Methods

Reactter provides several methods to manage states in a more efficient way. These methods are used to create and manipulate states in a more organized way.

Rt.lazyState

Rt.lazyState is a method that allows to create a state lazily in a dependency(class registered via the dependency injection). It’s useful when you want to create a state that depends on other states or variables.

Rt.lazyState is generally used in states declared with the late keyword.

Syntax

T Rt.lazyState<T extends ReactterState>(T stateFn(), Object instance);

Example

For example, you can create a state lazily in a class like this:

counter_controller.dart
1
import "package:reactter/reactter.dart";
2
3
class CountController {
4
final int initialCount;
5
6
late final uCount = Rt.lazyState(
7
() => UseState(this.initialCount),
8
this,
9
);
10
11
CountController([this.initialCount = 0]) {
12
UseEffect(() {
13
print("Count: ${uCount.value}");
14
}, [uCount]);
15
}
16
}

and then use it like this:

main.dart
1
import "./counter_controller.dart";
2
3
void main() {
4
final controller = Rt.create(() => CounterController(10));
5
controller.uCount.value += 2; // Count: 12
6
Rt.delete<CounterController>();
7
controller.uCount.value += 3; // Error: "Can't update when it's been disposed"
8
}

In the example, the uCount state is lazily declared inside the CountController class using Rt.lazyState . It’s accessed after creating the CountController instance, and when the instance is deleted, the state is automatically disposed, ensuring efficient resource management.

Rt.batch

The Rt.batch method allows multiple state changes to be grouped together, triggering them all at the end when the callback completes. This ensures that associated side effects occur only once, improving performance and reducing unnecessary re-renders.

Syntax

T Rt.batch(T callback());

Example

In this example, the UserController class demonstrates how to use the Rt.batch method to manage state updates efficiently.

user_controller.dart
1
import "package:reactter/reactter.dart";
2
3
class UserController {
4
final uName = UseState("John");
5
final uAge = UseState(25);
6
7
UserController() {
8
UseEffect(() {
9
print("Name: ${uName.value}, Age: ${uAge.value}");
10
}, [uName, uAge]);
11
}
12
13
void updateUserInfo(String name, int age) {
14
Rt.batch(() {
15
uName.value = name;
16
uAge.value = age;
17
});
18
}
19
}

By using Rt.batch , the updates to uName and uAge are grouped together, ensuring that the UseEffect hook’s callback is triggered only once after both state changes have been made. This improves performance by reducing unnecessary re-renders and ensuring that side effects, like printing the updated values, occur only once per batch of state changes.

Rt.untracked

The Rt.untracked method allows you to perform multiple state changes that are not tracked by the Reactter framework. This means that changes made using this method won’t trigger associated side effects or re-renders typically observed in reactive state management systems.

Syntax

T Rt.untracked(T callback());

Example

In this example, the UserController class demonstrates how to use the Rt.untracked method to update the states without triggering the associated side effects.

user_controller.dart
1
import "package:reactter/reactter.dart";
2
3
class UserController {
4
final uName = UseState("John");
5
final uAge = UseState(25);
6
7
UserController() {
8
UseEffect(() {
9
print("Name: ${uName.value}, Age: ${uAge.value}");
10
}, [uName, uAge]);
11
}
12
13
void updateUserInfo(String name, int age) {
14
Rt.untracked(() {
15
uName.value = name;
16
uAge.value = age;
17
});
18
}
19
}

By using Rt.untracked , the updates to uName and uAge are made without triggering the associated side effects, ensuring that the UseEffect hook’s callback is not triggered after these state changes. This is useful when you want to update states without causing re-renders or side effects, e.g., when initializing states or performing batch updates.