Skip to content

UseCompute

UseCompute is a hook that allows you to define a computation method ( computeValue ) to derive a value based on the current state of one or more dependencies. When any of these dependencies change, the hook recalculates the value and provides the updated result.

Syntax

UseCompute<T>(
T computeValue(),
List<RtState> dependencies,
);

UseCompute accepts these arguments:

  • computeValue : A function that returns a value based on the current state of the dependencies.
  • dependencies: A list of state( RtState , learn about it here) that the computation depends on. When any of these dependencies change, the value is recalculated.

Properties & Methods

UseCompute provides the following properties and methods:

  • value: A getter that allows you to read the computed value.
  • Methods inherited from RtState (Learn more here):

    • update : A method to notify changes after run a set of instructions.
    • refresh : A method to force to notify changes.
    • * bind : A method to bind an instance to it.
    • * unbind : A method to unbind an instance to it.
    • * dispose : A method to remove all listeners and free resources.

Usage

Declaration

UseCompute can be initialized using the constructor class:

3 collapsed lines
final uStateA = UseState<int>(0);
final uStateB = UseState<int>(0);
final uTotal = UseCompute<int>(
() => uStateA.value + uStateB.value,
[uStateA, uStateB],
);

Reading the computed value

UseCompute has a value property that allows you to read the computed value:

print("Total: ${uTotal.value}");

Computing the value

When any of the dependencies change, the value property recalculates the result based on the computeValue function, e.g.:

main.dart
1
final uStateA = UseState(1);
2
final uStateB = UseState(2);
3
4
final uResult = UseCompute(
5
// The `clamp` is a method that returns this num clamped
6
// to be in the range lowerLimit-upperLimit(e.g., 5-10).
7
() => addAB().clamp(5, 10),
8
[uStateA, uStateB],
9
);
10
11
int addAB() => uStateA.value + uStateB.value;
12
void printResult() => print("${addAB()} -> ${uResult.value}");
13
14
void main() {
15
Rt.on(
16
uResult,
17
Lifecycle.didUpdate,
18
(_, __) => print("uResult changed with: ${uResult.value}"),
19
);
20
21
printResult(); // 3 -> 5
22
uStateA.value += 1; // Will not notify change
23
printResult(); // 4 -> 5
24
uStateB.value += 2; // Will notify change
25
printResult(); // 6 -> 6
26
uStateA.value += 6; // Will notify change
27
printResult(); // 12 -> 10
28
uStateB.value -= 1; // Will not notify change
29
printResult(); // 13 -> 10
30
uStateA.value -= 5; // Will notify change
31
printResult(); // 8 -> 8
32
}

In above example, the value of uResult will be recalculated when the value of uStateA or uStateB changes. But when the calculated value is same as the previous value, it will not notify the change.

Using with Memo

UseCompute does not cache the computed value, meaning that it will computing the value every time the dependencies is changed, potentially impacting performance, especially if the computeValue is expensive. In this case, you should consider using  Memo  to cache the computed value, e.g.:

final addAB = Memo(
(Args2 args) => args.arg1 + args.arg2,
);
final uResult = UseCompute(
() => addAB(
Args2(uStateA.value, uStateB.value),
),
[uStateA, uStateB],
);

Updating the value

Use update method to notify changes after run a set of instructions:

uTotal.update((value) {
uTotal.value = 10;
});

Use refresh method to force to notify changes.

uTotal.refresh();

Listening to changes

When value has changed, the UseCompute will emit the following events(learn about it here):

  • Lifecycle.willUpdate event is triggered before the value change or update , refresh methods have been invoked.
  • Lifecycle.didUpdate event is triggered after the value change or update , refresh methods have been invoked.

Example of listening to changes:

1
Rt.on(
2
uTotal,
3
Lifecycle.didUpdate,
4
(_, state) => print("State value has changed to: ${state.value}"),
5
);