Skip to content

Commit 444f6bd

Browse files
committed
build: Release version 7.0.0.
1 parent bf91033 commit 444f6bd

9 files changed

Lines changed: 522 additions & 320 deletions

File tree

CHANGELOG.md

Lines changed: 27 additions & 50 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 117 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ See more examples [here](https://zapp.run/pub/flutter_reactter)!
9898
- [BuildContext.select](#buildcontextselect)
9999
- [Custom hooks](#custom-hooks)
100100
- [Lazy state](#lazy-state)
101+
- [Batch](#batch)
102+
- [Untracked](#untracked)
101103
- [Generic arguments](#generic-arguments)
102104
- [Memo](#memo)
103105
- [Difference between Signal and UseState](#difference-between-signal-and-usestate)
@@ -792,8 +794,32 @@ This lifecycles linked events, which are:
792794
- `Lifecycle.willUpdate`: is triggered anytime the instance's state is about to be updated. The event parameter is a `ReactterState`.
793795
- `Lifecycle.didUpdate`: is triggered anytime the instance's state has been updated. The event parameter is a `ReactterState`.
794796
- `Lifecycle.willUnmount`(exclusive of `flutter_reactter`): is triggered when the instance is about to be unmounted from the widget tree.
797+
- `Lifecycle.didUnmount`(exclusive of `flutter_reactter`): is triggered when the instance has been successfully unmounted from the widget tree.
795798
- `Lifecycle.destroyed`: is triggered when the instance has been destroyed.
796799

800+
You can extend your instances with [`LifecycleObserver`](https://pub.dev/documentation/reactter/latest/reactter/LifecycleObserver-class.html) mixin for observing and reacting to the various lifecycle events. e.g:
801+
802+
```dart
803+
class MyController with LifecycleObserver {
804+
final state = UseState('initial');
805+
806+
@override
807+
void onInitialized() {
808+
print("MyController has been initialized");
809+
}
810+
811+
@override
812+
void onDidUpdate(ReactterState? state) {
813+
print("$state has been changed");
814+
}
815+
}
816+
817+
final myController = Reactter.create(() => MyController());
818+
// MyController has been initialized
819+
myController.state.value = "value changed";
820+
// state has been changed
821+
```
822+
797823
### Shortcuts to manage events
798824

799825
Reactter offers several convenient shortcuts for managing events:
@@ -856,9 +882,8 @@ Reactter.emit(myController, Lifecycle.didUpdate, 'test param');
856882

857883
```dart
858884
UseEffect(
859-
<Function cleanup> Function callback,
885+
<Function cleanup> Function() callback,
860886
List<ReactterState> dependencies,
861-
[Object? instance],
862887
)
863888
```
864889

@@ -883,24 +908,20 @@ class MyController {
883908
// Cleanup - Execute before count state changed or 'Lifecycle.willUnmount' event
884909
print("Cleanup executed");
885910
};
886-
}, [count], this);
911+
}, [count]);
887912
}
888913
}
889914
```
890915

891-
Use `UseEffect.dispatchEffect` instead of instance argument to execute a `UseEffect` immediately.
916+
Use `UseEffect.runOnInit` to execute the callback effect on initialization.
892917

893918
```dart
894-
UseEffect(
895-
() => print("Excute immediately or by hook changes"),
919+
UseEffect.runOnInit(
920+
() => print("Excute immediately and by hook changes"),
896921
[someState],
897-
UseEffect.dispatchEffect
898922
);
899923
```
900924

901-
> **NOTE:**
902-
> If you don't add an `instance` argument to `UseEffect`, the `callback` won't execute on `Lifecycle.didMount`, and the `cleanup` won't execute on `Lifecycle.willUnmount` (theses `Lifecycle` events are used with `flutter_reactter` only).
903-
904925
## Rendering control
905926

906927
Rendering control provides the capability to observe specific instances or states, triggering re-renders of the widget tree as required. This methodology ensures a unified and responsive user interface, facilitating efficient updates based on changes in the application's state.
@@ -968,6 +989,8 @@ ReactterProvider<CounterController>(
968989
)
969990
```
970991

992+
Use [`ReactterProvider.lazy`](https://pub.dev/documentation/flutter_reactter/latest/flutter_reactter/ReactterProvider/ReactterProvider.lazy.html) to enable lazy-loading of the instance, ensuring it is only instantiated when necessary. While this feature enhances performance by deferring instantiation until required, it's important to note that it may result in the loss of lifecycle tracing.
993+
971994
> **NOTE:**
972995
> `ReactteProvider` is "scoped". So, the `builder` method will be rebuild when the instance or any `ReactterState` specified in [`BuildContext.watch`](#buildcontextwatch) or [`BuildContext.select`](#buildcontextselect) changes.
973996
@@ -1128,7 +1151,7 @@ ReactterSelector<T, V>(
11281151
- `child`: a `Widget` defined in the `child` property.
11291152

11301153
`ReactterSelector` determines if the widget tree of `builder` needs to be rebuild again by comparing the previous and new result of `selector`.
1131-
This evaluation only occurs if one of the selected states(`ReactterState`) gets updated, or by the instance if the `selector` does not have any selected states(`ReactterState`). e.g:
1154+
This evaluation only occurs if one of the selected states(`ReactterState`) gets updated, or by the instance if the `selector` does not have any selected states(`ReactterState`). e.g.:
11321155

11331156
```dart
11341157
class MyApp extends StatelessWidget {
@@ -1161,7 +1184,7 @@ class OtherWidget extends StatelessWidget {
11611184
}
11621185
```
11631186

1164-
`ReactterSelector` typing can be ommited, but the app must be wrapper by `ReactterScope`. e.g:
1187+
`ReactterSelector` typing can be ommited, but the app must be wrapper by `ReactterScope`. e.g.:
11651188

11661189
```dart
11671190
[...]
@@ -1281,13 +1304,13 @@ class OtherWidget extends StatelessWidget {
12811304
}
12821305
```
12831306

1284-
Use the first argument for obtaining the instance by `id`. e.g:
1307+
Use the first argument for obtaining the instance by `id`. e.g.:
12851308

12861309
```dart
12871310
final myControllerById = context.use<MyController>('uniqueId');
12881311
```
12891312

1290-
Use the nullable type to safely get the instance, avoiding exceptions if the instance is not found, and get `null` instead. e.g:
1313+
Use the nullable type to safely get the instance, avoiding exceptions if the instance is not found, and get `null` instead. e.g.:
12911314

12921315
```dart
12931316
final myController = context.use<MyController?>();
@@ -1335,7 +1358,7 @@ class OtherWidget extends StatelessWidget {
13351358
}
13361359
```
13371360

1338-
Use the first argument(`listenStates`) to specify the states that are to be listen on for rebuild. e.g:
1361+
Use the first argument(`listenStates`) to specify the states that are to be listen on for rebuild. e.g.:
13391362

13401363
```dart
13411364
[...]
@@ -1393,7 +1416,7 @@ V context.select<T, V>(
13931416
- `id`: to uniquely identify the instance.
13941417

13951418
`BuildContext.select` determines if the widget tree in scope of `BuildContext` needs to be rebuild again by comparing the previous and new result of `selector`.
1396-
This evaluation only occurs if one of the selected states(`ReactterState`) gets updated, or by the instance if the `selector` does not have any selected states(`ReactterState`). e.g:
1419+
This evaluation only occurs if one of the selected states(`ReactterState`) gets updated, or by the instance if the `selector` does not have any selected states(`ReactterState`). e.g.:
13971420

13981421
```dart
13991422
class MyApp extends StatelessWidget {
@@ -1424,7 +1447,7 @@ class OtherWidget extends StatelessWidget {
14241447
}
14251448
```
14261449

1427-
`BuildContext.select` typing can be ommited, but the app must be wrapper by `ReactterScope`. e.g:
1450+
`BuildContext.select` typing can be ommited, but the app must be wrapper by `ReactterScope`. e.g.:
14281451

14291452
```dart
14301453
[...]
@@ -1535,6 +1558,81 @@ class MyController {
15351558
> **IMPORTANT**:
15361559
> A state(`ReactterState`) declared with the `late` keyword and not using `Reactter.lazyState` is outside the context of the instance where it was declared, and therefore the instance does not notice about its changes.
15371560
1561+
## Batch
1562+
1563+
```dart
1564+
T Reactter.batch<T>(T Function() callback)
1565+
```
1566+
1567+
The [`batch`](https://pub.dev/documentation/reactter/latest/reactter/ReactterInterface/batch.html) function allows you to combine multiple state changes to be grouped together, ensuring that any associated side effects are only triggered once, improving performance and reducing unnecessary re-renders. e.g.:
1568+
1569+
```dart
1570+
final stateA = UseState(0);
1571+
final stateB = UseState(0);
1572+
final computed = UseCompute(
1573+
() => stateA.value + stateB.value,
1574+
[stateA, stateB],
1575+
);
1576+
1577+
final batchReturned = Reactter.batch(() {
1578+
stateA.value = 1;
1579+
stateB.value = 2;
1580+
1581+
print(computed.value); // 0 -> because the batch operation is not completed yet.
1582+
1583+
return stateA.value + stateB.value;
1584+
});
1585+
1586+
print(batchReturned); // 3
1587+
print(computed.value); // 3 -> because the batch operation is completed.
1588+
```
1589+
1590+
Batches can be nested and updates will be flushed when the outermost batch call completes. e.g.:
1591+
1592+
```dart
1593+
final stateA = UseState(0);
1594+
final stateB = UseState(0);
1595+
final computed = UseCompute(
1596+
() => stateA.value + stateB.value,
1597+
[stateA, stateB],
1598+
);
1599+
1600+
Reactter.batch(() {
1601+
stateA.value = 1;
1602+
print(computed.value); // 0;
1603+
1604+
Reactter.batch(() {
1605+
stateB.value = 2;
1606+
print(computed.value); // 0;
1607+
});
1608+
1609+
print(computed.value); // 0;
1610+
});
1611+
1612+
print(computed.value); // 3;
1613+
```
1614+
1615+
## Untracked
1616+
1617+
```dart
1618+
T Reactter.untracked<T>(T Function() callback)
1619+
```
1620+
1621+
The [`untracked`](https://pub.dev/documentation/reactter/latest/reactter/ReactterInterface/untracked.html) function helps you to execute the given `callback` function without tracking any state changes. This means that any state changes that occur inside the `callback` function will not trigger any side effects. e.g.:
1622+
1623+
```dart
1624+
final state = UseState(0);
1625+
final computed = UseCompute(() => state.value + 1, [state]);
1626+
1627+
Reactter.untracked(() {
1628+
state.value = 2;
1629+
1630+
print(computed.value); // 1 -> because the state change is not tracked
1631+
});
1632+
1633+
print(computed.value); // 1 -> because the state change is not tracked
1634+
```
1635+
15381636
## Generic arguments
15391637

15401638
Generic arguments are objects of the `Args` class that represent the arguments of the specified types.
@@ -1576,7 +1674,7 @@ In each of the methods it provides theses methods and properties:
15761674
> typedef ArgX+n<T> = Args+n<T, (...), T>;
15771675
> ```
15781676
>
1579-
> e.g 4 arguments:
1677+
> e.g. 4 arguments:
15801678
>
15811679
> ```dart
15821680
> class Args4<A, A2, A3, A4> extends Args3<A, A2, A3> {
@@ -1592,7 +1690,7 @@ In each of the methods it provides theses methods and properties:
15921690
> ```
15931691
15941692
> **NOTE:**
1595-
> Use `ary` Function extention to convert any `Function` with positional arguments to `Function` with generic argument, e.g:
1693+
> Use `ary` Function extention to convert any `Function` with positional arguments to `Function` with generic argument, e.g.:
15961694
>
15971695
> ```dart
15981696
> int addNum(int num1, int num2) => num1 + num2;

0 commit comments

Comments
 (0)