Skip to content

Commit d4927df

Browse files
committed
Merge branch 'develop'
2 parents 8e13d1c + bc7f4d8 commit d4927df

31 files changed

+264
-325
lines changed

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,21 @@
11
# Reactter
2+
3+
## 4.1.0
4+
5+
### Enhancements
6+
7+
- **perf(core)**: Improve performance for changing states.
8+
- **perf(engine)**: Improve management for context dependencies.
9+
10+
### Fixes
11+
12+
- **fix(core)**: Remove the callbacks of one events when the instance will be disposed.
13+
14+
### Internal
15+
16+
- **refactor(example)**: Improve examples and fix some bugs.
17+
- **doc**: Fix documentation.
18+
219
## 4.0.0
320

421
### Enhancements

README.md

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ ____
99
[![Flutter Reactter](https://img.shields.io/pub/v/flutter_reactter?color=1d7fac&labelColor=29b6f6&label=flutter_reactter&logo=flutter)](https://pub.dev/packages/flutter_reactter)
1010
[![Pub points](https://img.shields.io/pub/points/reactter?color=196959&labelColor=23967F&logo=dart)](https://pub.dev/packages/reactter/score)
1111
[![MIT License](https://img.shields.io/github/license/2devs-team/reactter?color=a85f00&labelColor=F08700&logoColor=fff&logo=Open%20Source%20Initiative)](https://github.com/2devs-team/reactter/blob/master/LICENSE)
12-
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/2devs-team/reactter/Test?logo=github)](https://github.com/2devs-team/reactter/actions)
12+
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/2devs-team/reactter/dart.yml?branch=master)](https://github.com/2devs-team/reactter/actions)
1313
[![Codecov](https://img.shields.io/codecov/c/github/2devs-team/reactter?logo=codecov)](https://app.codecov.io/gh/2devs-team/reactter)
1414

1515
**A light, powerful and reactive state management.**
@@ -29,6 +29,7 @@ ____
2929
Let's see a small and simple example:
3030

3131
```dart
32+
import 'dart:async';
3233
import 'package:flutter/material.dart';
3334
import 'package:flutter_reactter/flutter_reactter.dart';
3435
@@ -40,11 +41,7 @@ void main() {
4041
Reactter.on(count, Lifecycle.didUpdate, (_, __) => print('Count: $count'));
4142
4243
// Change the `value` in any time.
43-
Future.doWhile(() async {
44-
count.value++;
45-
await Future.delayed(const Duration(seconds: 1));
46-
return true;
47-
});
44+
Timer.periodic(Duration(seconds: 1), (_) => count.value++);
4845
4946
// And you can use in flutter like this:
5047
runApp(
@@ -184,17 +181,20 @@ import 'package:flutter_reactter/flutter_reactter.dart';
184181

185182
[`ReactterContext`](https://pub.dev/documentation/reactter/latest/core/ReactterContext-class.html) is a abstract class that allows to manages [`ReactterHook`](https://pub.dev/documentation/reactter/latest/core/ReactterHook-class.html) and provides life-cycle events.
186183

187-
In flutter, using [`ReactterProvider`](https://pub.dev/documentation/flutter_reactter/latest/widgets/ReactterProvider-class.html), it's a way to share the state between widgets without having to explicitly pass a prop through every level of the tree.
188-
189184
You can use it's functionalities, creating a class that extends it:
190185

191186
```dart
192187
class AppContext extends ReactterContext {}
193188
```
194189

190+
You can use the [shortcuts to manage instances](#shortcuts-to-manage-instances) or [using `UseContext` hook](#using-usecontext-hook) to access it.
191+
195192
> **RECOMMENDED:**
196193
> Name class with `Context` suffix, for easy locatily.
197194

195+
> **NOTE:**
196+
> In flutter, using [`ReactterProvider`](https://pub.dev/documentation/flutter_reactter/latest/widgets/ReactterProvider-class.html), it's a way to share the state between widgets without having to explicitly pass a property through every level of the tree.
197+
198198
### Lifecycle of `ReactterContext`
199199

200200
`ReactterContext` has the following [Lifecycle](https://pub.dev/documentation/reactter/latest/core/Lifecycle.html) events:
@@ -217,20 +217,7 @@ class AppContext extends ReactterContext {}
217217

218218
- **`Lifecycle.destroyed`**: Event when the instance did be destroyed by `ReactterInstanceManager`.
219219

220-
You can put it on listen, using `Reactter.on` or `UseEvent<T>().on`, for example:
221-
222-
```dart
223-
Reactter.on(
224-
ReactterInstance<AppContext>(),
225-
Lifecycle.didUpdate,
226-
(AppContext inst, ReactterState state) => print("Instance: $inst, state: $state"),
227-
);
228-
// or
229-
UseEvent<AppContext>().on(
230-
Lifecycle.didUpdate,
231-
(AppContext inst, ReactterState state) => print("Instance: $inst, state: $state"),
232-
);
233-
```
220+
You can use the [shortcuts](#shortcuts-to-manage-events) or [`UseEvent` hook](#using-useevent-hook) to listen to these events.
234221

235222
### Shortcuts to manage instances
236223

@@ -353,7 +340,7 @@ class AppContext extends ReactterContext {
353340

354341
> **NOTE:** If you're not sure that you got the instance from the beginning, you need to use the `UseEffect` as shown in the example above.
355342
>
356-
> **NOTE:** The context that you need to get, must be created by [`ReactterInstanceManager`](https://pub.dev/documentation/reactter/latest/core/ReactterInstanceManager-class.html).
343+
> **NOTE:** The context that you need to get, must be created by [`ReactterInstanceManager`](https://pub.dev/documentation/reactter/latest/core/ReactterInstanceManager-mixin.html).
357344

358345
### Using `UseEvent` hook
359346

@@ -398,7 +385,8 @@ UseEvent<AppContext>().emit(Events.SomeEvent, 'Parameter');
398385

399386
[`Signal`](https://pub.dev/documentation/reactter/latest/core/Signal-class.html) is a class that store a `value` of any type and notify the listeners when the `value` is updated.
400387

401-
In flutter, using [`ReactterWatcher`](https://pub.dev/documentation/flutter_reactter/latest/widgets/ReactterWatcher-class.html), it's a way to keep the widgets automatically updates, accessing the value of signal reactively.
388+
> **NOTE:**
389+
> In flutter, using [`ReactterWatcher`](https://pub.dev/documentation/flutter_reactter/latest/widgets/ReactterWatcher-class.html), it's a way to keep the widgets automatically updates, accessing the value of signal reactively.
402390

403391
You can create a new `Signal`, like so:
404392

@@ -454,7 +442,7 @@ userSignal.refresh();
454442
When `value` is changed, the `Signal` will emitted the following events:
455443

456444
- `Lifecycle.willUpdate` event is triggered before the `value` change or `update`, `refresh` methods have been invoked.
457-
- `Lifecicle.didUpdate` is triggered after the `value` change or `update`, `refresh` methods have been invoked.
445+
- `Lifecicle.didUpdate` event is triggered after the `value` change or `update`, `refresh` methods have been invoked.
458446

459447
> **NOTE:**
460448
> When you do any arithmetic operation between two `Signal`s, its return a `Obj`, for example: `1.signal + 2.signal` return `3.obj`.
@@ -521,7 +509,7 @@ userState.refresh();
521509
When `value` is changed, the `UseState` will emitted the following events:
522510

523511
- `Lifecycle.willUpdate` event is triggered before the `value` change or `update`, `refresh` methods have been invoked.
524-
- `Lifecicle.didUpdate` is triggered after the `value` change or `update`, `refresh` methods have been invoked.
512+
- `Lifecicle.didUpdate` event is triggered after the `value` change or `update`, `refresh` methods have been invoked.
525513

526514
### Different between `UseState` and `Signal`
527515

@@ -531,15 +519,15 @@ Both `UseState` and `Signal` represent a state(`ReactterState`). But there are a
531519

532520
With `UseState` is necessary use `value` property every time for read or write its state. But with `Signal` it is not necessary, improving code readability.
533521

534-
In Flutter, to use `UseState` you need to provide its `ReactterContext` to the Widget tree,with `ReactterProvider` or `ReactterComponent` and access it through of `BuildContext`. With `Signal` use `ReactterWatcher` only, it's very simple.
522+
In Flutter, to use `UseState` you need to provide its `ReactterContext` to the Widget tree, with `ReactterProvider` or `ReactterComponent` and access it through of `BuildContext`. With `Signal` use `ReactterWatcher` only, it's very simple.
535523

536524
But it is not all advantages for `Signal`, although it is good for global states and for improving code readability, it is prone to antipatterns and makes debugging difficult(This will be improved in the following versions).
537525

538526
The decision between which one to use is yours. You can use one or both without them getting in the way. And you can even replace a `UseState` with a `Signal` into a `ReactterContext`.
539527

540528
### Using `UseAsyncState` hook
541529

542-
[`UseAsyncState`](https://pub.dev/documentation/reactter/latest/reactter/UseAsyncState-class.html) is a `ReactterHook` with the same functionality as `UseState` but provides a `asyncValue` method, which will be obtained when `resolve` method is executed.
530+
[`UseAsyncState`](https://pub.dev/documentation/reactter/latest/hooks/UseAsyncState-class.html) is a `ReactterHook` with the same functionality as `UseState` but provides a `asyncValue` method, which will be obtained when `resolve` method is executed.
543531

544532
```dart
545533
class TranslateArgs {
@@ -594,7 +582,7 @@ final valueComputed = asyncState.when<String>(
594582

595583
### Using `UseReducer` hook
596584

597-
[`UseReducer`](https://pub.dev/documentation/reactter/latest/core/UseReducer-class.html) is a `ReactterHook` that manages state using reducer method. An alternative to `UseState`.
585+
[`UseReducer`](https://pub.dev/documentation/reactter/latest/hooks/UseReducer-class.html) is a `ReactterHook` that manages state using reducer method. An alternative to `UseState`.
598586

599587
> **RECOMMENDED:**
600588
> `UseReducer` is usually preferable to `UseState` when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one.
@@ -706,7 +694,7 @@ class AppContext extends ReactterContext {
706694
);
707695
708696
return () {
709-
// Cleanup - Execute Before count state changed or 'willUnmount' event
697+
// Cleanup - Execute before count state changed or 'willUnmount' event
710698
print("Cleanup executed");
711699
};
712700
}, [count], this);
@@ -969,6 +957,7 @@ class CounterComponent extends ReactterComponent<AppContext> {
969957
- [Documentation](https://pub.dev/documentation/reactter/latest)
970958
- [Examples](https://github.com/2devs-team/reactter/tree/master/examples)
971959
- [Counter example](https://github.com/2devs-team/reactter/tree/master/examples/lib/counter)
960+
- [Calculator example](https://github.com/2devs-team/reactter/tree/master/examples/lib/calculator)
972961
- [Todos example](https://github.com/2devs-team/reactter/tree/master/examples/lib/todos)
973962
- [Shopping cart example](https://github.com/2devs-team/reactter/tree/master/examples/lib/shopping_cart)
974963
- [Tree widget example](https://github.com/2devs-team/reactter/tree/master/examples/lib/tree)
@@ -979,7 +968,7 @@ class CounterComponent extends ReactterComponent<AppContext> {
979968

980969
We want to keeping adding features for `Reactter`, those are some we have in mind order by priority:
981970

982-
- Widget to control re-render using only hooks
971+
- Widget to control re-render using only hooks.
983972
- Async context.
984973
- Do benchmarks and improve performance.
985974

@@ -1004,5 +993,5 @@ Any idea is welcome!
1004993

1005994
# Authors
1006995

1007-
- **[Carlos León](_blank)** - <carleon.dev@gmail.com>
996+
- **[Carlos León](https://twitter.com/CarLeonDev)** - <carleon.dev@gmail.com>
1008997
- **[Leo Castellanos](https://twitter.com/leoocast10)** - <leoocast.dev@gmail.com>

examples/lib/api/contexts/api_context.dart renamed to examples/lib/api/api_context.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import 'package:flutter/material.dart';
44
import 'package:http/http.dart' as http;
55
import 'package:flutter_reactter/flutter_reactter.dart';
66

7-
import '../models/repository.dart';
8-
import '../models/user.dart';
7+
import 'models/repository.dart';
8+
import 'models/user.dart';
99

1010
class ApiContext extends ReactterContext {
1111
final formKey = GlobalKey<FormState>();

examples/lib/api/api_page.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_reactter/flutter_reactter.dart';
33

4-
import 'contexts/api_context.dart';
4+
import 'api_context.dart';
55
import 'models/repository.dart';
66
import 'models/user.dart';
77
import 'repository_item.dart';

examples/lib/api/contexts/repository_context.dart

Lines changed: 0 additions & 9 deletions
This file was deleted.

examples/lib/api/contexts/user_context.dart

Lines changed: 0 additions & 9 deletions
This file was deleted.

examples/lib/api/repository_item.dart

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,65 @@
11
import 'package:flutter/material.dart';
2-
import 'package:flutter_reactter/flutter_reactter.dart';
32
import 'package:url_launcher/url_launcher.dart';
43

54
import 'badget.dart';
6-
import 'contexts/repository_context.dart';
75
import 'models/repository.dart';
86

9-
class RepositoryItem extends ReactterComponent<RepositoryContext> {
7+
class RepositoryItem extends StatelessWidget {
108
const RepositoryItem({Key? key, required this.repository}) : super(key: key);
119

1210
final Repository repository;
1311

1412
@override
15-
get builder => () => RepositoryContext()..repository.value = repository;
16-
17-
@override
18-
Widget render(RepositoryContext ctx, BuildContext context) {
19-
final repo = ctx.repository.value;
20-
21-
if (repo == null) return const SizedBox.shrink();
22-
13+
Widget build(BuildContext context) {
2314
return Column(
2415
children: [
2516
CircleAvatar(
2617
radius: 42,
2718
backgroundColor: Colors.transparent,
28-
backgroundImage: NetworkImage(repo.owner.avatarUrl),
19+
backgroundImage: NetworkImage(repository.owner.avatarUrl),
2920
),
3021
GestureDetector(
3122
child: Text(
32-
repo.fullName,
23+
repository.fullName,
3324
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
3425
decoration: TextDecoration.underline,
3526
fontWeight: FontWeight.bold,
3627
color: Colors.blue,
3728
),
3829
),
3930
onTap: () async {
40-
final url = Uri.parse(repo.htmlUrl);
31+
final url = Uri.parse(repository.htmlUrl);
4132
if (await canLaunchUrl(url)) {
4233
launchUrl(url);
4334
}
4435
},
4536
),
46-
Text(repo.description, style: Theme.of(context).textTheme.bodyLarge),
37+
Text(repository.description,
38+
style: Theme.of(context).textTheme.bodyLarge),
4739
const SizedBox(height: 16),
4840
Row(
4941
mainAxisSize: MainAxisSize.min,
5042
children: [
5143
Badget(
5244
icon: Icons.star,
5345
label: "Stars",
54-
value: "${repo.stargazersCount}",
46+
value: "${repository.stargazersCount}",
5547
labelColor: const Color(0xfff7b05b),
5648
valueColor: const Color(0xffc68d49),
5749
),
5850
const SizedBox(width: 8),
5951
Badget(
6052
icon: Icons.visibility_rounded,
6153
label: "Watching",
62-
value: "${repo.watchersCount}",
54+
value: "${repository.watchersCount}",
6355
labelColor: const Color(0xff23967F),
6456
valueColor: const Color(0xff196959),
6557
),
6658
const SizedBox(width: 8),
6759
Badget(
6860
icon: Icons.call_split,
6961
label: "Forks",
70-
value: "${repo.forks}",
62+
value: "${repository.forks}",
7163
labelColor: const Color(0xff8075FF),
7264
valueColor: const Color(0xff5a52b3),
7365
),

examples/lib/api/user_item.dart

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,16 @@
11
import 'package:flutter/material.dart';
2-
import 'package:flutter_reactter/flutter_reactter.dart';
32
import 'package:url_launcher/url_launcher.dart';
43

54
import 'badget.dart';
6-
import 'contexts/user_context.dart';
75
import 'models/user.dart';
86

9-
class UserItem extends ReactterComponent<UserContext> {
7+
class UserItem extends StatelessWidget {
108
const UserItem({Key? key, required this.user}) : super(key: key);
119

1210
final User user;
1311

1412
@override
15-
get builder => () => UserContext()..user.value = user;
16-
17-
@override
18-
Widget render(UserContext ctx, BuildContext context) {
19-
final user = ctx.user.value;
20-
21-
if (user == null) return const SizedBox.shrink();
22-
13+
Widget build(BuildContext context) {
2314
return Column(
2415
children: [
2516
CircleAvatar(

examples/lib/main.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ final items = <ListItem>[
2020
"ReactterWatcher",
2121
"Signal",
2222
],
23-
() => CounterPage(),
23+
() => const CounterPage(),
2424
),
2525
ExampleItem(
2626
"Calculator",
@@ -73,10 +73,8 @@ final items = <ListItem>[
7373
"Search user or repository and show info about it.",
7474
[
7575
"ReactterContext",
76-
"ReactterComponent",
7776
"ReactterProvider",
7877
"UseAsyncState",
79-
"UseState",
8078
],
8179
() => const ApiPage(),
8280
),

examples/lib/todos/todos_context.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class TodosContext extends ReactterContext {
3333
}
3434

3535
List<Todo> getTodosBy(TodoListType todoListType) {
36-
if (todoListType == TodoListType.pending) {
36+
if (todoListType == TodoListType.todo) {
3737
return state.value.todos.where((todo) => !todo.isDone).toList();
3838
}
3939

0 commit comments

Comments
 (0)