Skip to content

Commit

Permalink
doc: Add UseCompute documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
CarLeonDev committed May 22, 2024
1 parent b21abdb commit 5045df2
Showing 1 changed file with 186 additions and 0 deletions.
186 changes: 186 additions & 0 deletions website/src/content/docs/hooks/use_compute.mdx
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',
}}/>

0 comments on commit 5045df2

Please sign in to comment.