-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b21abdb
commit 5045df2
Showing
1 changed file
with
186 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
--- | ||
title: UseCompute | ||
description: A hook that computes a value based on the state of other hooks. | ||
sidebar: | ||
order: 4 | ||
--- | ||
|
||
import { HE, HM, HT } from '@/components/Highlight'; | ||
import { Code } from "@astrojs/starlight/components"; | ||
import MDXRedry from '@/components/MDXRedry.astro'; | ||
import StateMethodsLite from '@/content/docs/shareds/state_methods_lite.mdx'; | ||
import * as NoteLateState from '@/content/docs/shareds/note_late_state.mdx'; | ||
import * as NoteStateValueNotifies from '@/content/docs/shareds/note_state_value_notifies.mdx'; | ||
import * as ListeningChangesState from '@/content/docs/shareds/listening_changes_state.mdx'; | ||
|
||
<HT><a href="https://pub.dev/documentation/reactter/latest/reactter/UseCompute-class.html" target="_blank">`UseCompute`</a></HT> is a [hook](/reactter/core_concepts/hooks) that allows you to define a computation method (<HM>`computeValue`</HM>) 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 | ||
|
||
```dart showLineNumbers=false | ||
UseCompute<T>( | ||
T computeValue(), | ||
List<ReactterState> dependencies, | ||
); | ||
``` | ||
|
||
<HT>`UseCompute`</HT> accepts these properties: | ||
|
||
- <HM>`computeValue`</HM>: A function that returns a value based on the current state of the dependencies. | ||
- `dependencies`: A list of state(<HT>`ReactterState`</HT>, learn about it [here](/reactter/core_concepts/state_management/#state)) that the computation depends on. When any of these dependencies change, the `value` is recalculated. | ||
|
||
## Properties & Methods | ||
|
||
<HT>`UseCompute`</HT> provides the following properties and methods: | ||
|
||
- `value`: A getter that allows you to read the computed value. | ||
<StateMethodsLite/> | ||
|
||
## Usage | ||
|
||
### Declaration | ||
|
||
<HT>`UseCompute`</HT> can be initialized using the constructor class: | ||
|
||
```dart showLineNumbers=false "UseCompute" collapse={1-3} | ||
final uStateA = UseState<int>(0); | ||
final uStateB = UseState<int>(0); | ||
final uTotal = UseCompute<int>( | ||
() => uStateA.value + uStateB.value, | ||
[uStateA, uStateB], | ||
); | ||
``` | ||
|
||
<MDXRedry mdx={NoteLateState} vars={{stateName: 'UseCompute'}}> | ||
<Fragment slot="exampleCode"> | ||
```dart title="item_controller.dart" collapse={1-6, 14-31} "late" "Reactter.lazyState" "UseCompute" | ||
class ItemController { | ||
final Product product; | ||
final uPrice = UseState<int>(0); | ||
final uQuantity = UseState<int>(0); | ||
late final uTotal = Reactter.lazyState( | ||
() => UseCompute<int>( | ||
() => uPrice.value * uQuantity.value, | ||
[uPrice, uQuantity], | ||
), | ||
this, | ||
); | ||
int get price => uPrice.value; | ||
int get quantity => uQuantity.value; | ||
int get total => uTotal.value; | ||
ItemController(this.product) { | ||
uPrice.value = product.price; | ||
uQuantity.value = product.quantity; | ||
} | ||
void setPrice(int price) { | ||
uPrice.value = price; | ||
} | ||
void setQuantity(int quantity) { | ||
uQuantity.value = quantity; | ||
} | ||
} | ||
``` | ||
</Fragment> | ||
</MDXRedry> | ||
|
||
### Reading the computed value | ||
|
||
<HT>`UseCompute`</HT> has a `value` property that allows you to read the computed value: | ||
|
||
```dart showLineNumbers=false ".value" | ||
print("Total: ${uTotal.value}"); | ||
``` | ||
|
||
### Computing the value | ||
|
||
When any of the `dependencies` change, the `value` property recalculates the result based on the <HM>`computeValue`</HM> function, e.g.: | ||
|
||
|
||
```dart title="main.dart" "UseCompute" "UseState" "Reactter.on" "Lifecycle.didUpdate" "uStateA" "uStateB" "uResult" "uStateA.value" "uStateB.value" "uResult.value" | ||
final uStateA = UseState(1); | ||
final uStateB = UseState(2); | ||
final uResult = UseCompute( | ||
// The `clamp` is a method that returns this num clamped | ||
// to be in the range lowerLimit-upperLimit(e.g., 5-10). | ||
() => addAB().clamp(5, 10), | ||
[uStateA, uStateB], | ||
); | ||
int addAB() => uStateA.value + uStateB.value; | ||
void printResult() => print("${addAB()} -> ${uResult.value}"); | ||
void main() { | ||
Reactter.on( | ||
uResult, | ||
Lifecycle.didUpdate, | ||
(_, __) => print("uResult changed with: ${uResult.value}"), | ||
); | ||
printResult(); // 3 -> 5 | ||
uStateA.value += 1; // Will not notify change | ||
printResult(); // 4 -> 5 | ||
uStateB.value += 2; // Will notify change | ||
printResult(); // 6 -> 6 | ||
uStateA.value += 6; // Will notify change | ||
printResult(); // 12 -> 10 | ||
uStateB.value -= 1; // Will not notify change | ||
printResult(); // 13 -> 10 | ||
uStateA.value -= 5; // Will notify change | ||
printResult(); // 8 -> 8 | ||
} | ||
``` | ||
|
||
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. | ||
|
||
<MDXRedry mdx={NoteStateValueNotifies} vars={{ | ||
stateName: 'UseCompute', | ||
}}/> | ||
|
||
### Using with Memo | ||
|
||
<HT>`UseCompute`</HT> 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 <HM>`computeValue`</HM> is expensive. In this case, you should consider using <HT>[`Memo`](/reactter/classes/memo)</HT> to cache the computed `value`, e.g.: | ||
|
||
```dart showLineNumbers=false "UseCompute" "Memo" | ||
final addAB = Memo( | ||
(Args2 args) => args.arg1 + args.arg2, | ||
); | ||
final uResult = UseCompute( | ||
() => addAB( | ||
Args2(uStateA.value, uStateB.value), | ||
), | ||
[uStateA, uStateB], | ||
); | ||
``` | ||
|
||
### Updating the value | ||
|
||
Use <HM>`update`</HM> method to notify changes after run a set of instructions: | ||
|
||
```dart showLineNumbers=false ".update" | ||
uTotal.update((value) { | ||
uTotal.value = 10; | ||
}); | ||
``` | ||
|
||
Use <HM>`refresh`</HM> method to force to notify changes. | ||
|
||
```dart showLineNumbers=false ".refresh" | ||
uTotal.refresh(); | ||
``` | ||
|
||
### Listening to changes | ||
|
||
<MDXRedry mdx={ListeningChangesState} vars={{ | ||
stateName: 'UseCompute', | ||
stateVariable: 'uTotal', | ||
}}/> |