Skip to content

Commit

Permalink
Merge pull request #14 from jinyus/patch-2
Browse files Browse the repository at this point in the history
Make untracked local
  • Loading branch information
jinyus authored Jan 1, 2024
2 parents bb3339c + 0ddb295 commit eed87b0
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 8 deletions.
4 changes: 4 additions & 0 deletions state_beacon/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.15.0

- Beacon.untracked() now only hide the update/access from encompassing effects.

## 0.14.6

- Add `tryCatch` method to AsyncValue class that executes a future and returns an AsyncData or AsyncError
Expand Down
15 changes: 13 additions & 2 deletions state_beacon/lib/src/base_beacon.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ abstract class BaseBeacon<T> implements ValueListenable<T> {
if (_isEmpty) {
throw UninitializeLazyReadException();
}

if (isRunningUntracked()) {
// if we are running untracked, we don't want to add the current effect to the listeners
return _value;
}

Expand All @@ -76,8 +78,17 @@ abstract class BaseBeacon<T> implements ValueListenable<T> {

void _notifyOrDeferBatch() {
if (isRunningUntracked()) {
return;
} else if (_isRunningBatchJob()) {
final currentEffects = <EffectClosure>[];
for (final effect in _effectStack) {
_listeners.remove(effect.func);
currentEffects.add(effect.func);
}
reAddListeners = () {
_listeners.addAll(currentEffects);
};
}

if (_isRunningBatchJob()) {
_listenersToPingAfterBatchJob.addAll(_listeners.items);
} else {
_notifyListeners();
Expand Down
5 changes: 5 additions & 0 deletions state_beacon/lib/src/listeners.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ class Listeners {
return added;
}

void addAll(Iterable<EffectClosure> items) {
_set.addAll(items);
_list.addAll(items);
}

bool remove(EffectClosure item) {
bool removed = _set.remove(item);
if (removed) {
Expand Down
22 changes: 20 additions & 2 deletions state_beacon/lib/src/untracked.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
import 'package:state_beacon/src/common.dart';

var _untrackedStack = 0;

bool isRunningUntracked() => _untrackedStack > 0;

// when running untracked, we will remove the current effects from the beacon's listeners
// so they won't be notified when the value is accessed;
// therefore, we need to re-add them after the untracked block is done
VoidCallback? reAddListeners;

void doUntracked(void Function() fn) {
if (isRunningUntracked()) {
fn();
return;
}

_untrackedStack++;
fn();
_untrackedStack--;

try {
fn();
} finally {
_untrackedStack--;
reAddListeners?.call();
reAddListeners = null;
}
}
2 changes: 1 addition & 1 deletion state_beacon/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: state_beacon
description: A reactive primitive and simple state managerment solution for dart and flutter
version: 0.14.6
version: 0.15.0
repository: https://github.com/jinyus/dart_beacon

environment:
Expand Down
28 changes: 25 additions & 3 deletions state_beacon/test/untracked_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,42 @@ void main() {
test('should not send notification when doing untracked updates', () {
final age = Beacon.writable<int>(10);
var callCount = 0;
age.subscribe((_) => callCount++);

Beacon.createEffect(() {
age.value;
callCount++;
Beacon.untracked(() {
age.value = 15;
});
});

expect(callCount, equals(0));
expect(callCount, equals(1));
expect(age.value, 15);

age.value = 20;
expect(callCount, equals(2));
});

test('should not send notification when doing nested untracked updates', () {
final age = Beacon.writable<int>(10);
var callCount = 0;

Beacon.createEffect(() {
age.value;
callCount++;
Beacon.untracked(() {
age.value = 15;
Beacon.untracked(() {
age.value = 20;
});
});
});

expect(callCount, equals(1));
expect(age.value, 20);

age.value = 25;
expect(callCount, equals(2));
});

test('should not send notification when doing untracked access', () {
Expand All @@ -29,10 +51,10 @@ void main() {

Beacon.createEffect(() {
age.value;
callCount++;
Beacon.untracked(() {
name.value;
});
callCount++;
});

expect(callCount, equals(1));
Expand Down

0 comments on commit eed87b0

Please sign in to comment.