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:
1import "package:reactter/reactter.dart";2
3class 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:
1import "./counter_controller.dart";2
3void main() {4 final controller = Rt.create(() => CounterController(10));5 controller.uCount.value += 2; // Count: 126 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.registerState
Rt.registerState is a method that allows to register a RtState instance.
All states created must be registered using this method for proper management and disposal.
Syntax
T Rt.registerState<T extends RtState>(T stateFn());Example
In this example, the custom state using RtState class is created and registered using Rt.registerState method.
1class MyState extends RtState<MyState> {2 int _value = 0;3 int get value => _value;4 set value(int n) {5 if (n == _value) return;6 update(() => _value = n); // set new value and notify observers7 }8
9 MyState([int value = 0]) : _value = value;10}11
12final state = Rt.registerState<MyState>(() => MyState()); // Register state8 collapsed lines
13
14Rt.on(15 state,16 Lifecycle.didUpdate,17 (_, __) => print('State updated: ${state.value}')18);19
20state.value = 42; // Calls update internally 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.
1import "package:reactter/reactter.dart";2
3class 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.
1import "package:reactter/reactter.dart";2
3class 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.