state_beacon_flutter
A reactive primitive and simple state managerment solution for dart and flutter
3.1.1
3.1K downloads/mo
#4592 most downloaded on pub.dev
zupat/dart_beacon
What this package is like to depend on
Last release 3 months ago
21 May 2026
Ships unpredictably
gaps range from 8 days to 1.4 years
Nearly every release is documented
notes for 19 of 19 stable releases
Nothing withdrawn
no release was ever pulled
2 years old
19 releases · first in 2024
18 releases in the last 12 months
see the full history below
Release timeline
19 releases · May 2024 to May 2026Releases
latest 19-
3.1.121 May 2026Release notes
Open source →- [Feat] Add
asErrorgetter to theAsyncValue. This allows users to easily retrieve theAsyncErrorinstance when the state is an error, or null otherwise.
- [Feat] Add
-
3.1.002 Mar 2026Release notes
Open source →What's Changed
- refactor: improve edge-case status check logic in DerivedSubscription by @zupat in #173
- refactor: simplify status comparison in stale method for DerivedBeacon and DerivedSubscription by @zupat in #174
- Feat: Add ProgressBeacon by @zupat in #179
- Refactor/progress-beacon by @zupat in #180
- feat: add ProgressStatus enum and update ProgressBeacon status management by @zupat in #182
New Contributors
Full Changelog: v3.0.1...v3.1.0
Release notes
Open source →-
[Feat] Add
ProgressBeacon(Beacon.progress) with support for status tracking (ProgressStatus), manual control (start/stop/pause/resume), looping, andBeaconGroupintegration. -
[Refactor] Internal improvements for
DerivedSubscriptionandDerivedBeaconstatus propagation.
-
3.0.107 Jan 2026Release notes
Open source →What's Changed
- refactor error handling in FutureBeacon to use pattern matching by @zupat in #169
- fix: edgecase in derived sub with startNow=false by @zupat in #171
Full Changelog: v3.0.0...v3.0.1
Release notes
Open source →- [Fix] Bug where subscriptions to derived beacons with startNow=false would not run when the beacon was accessed after the subscription was created but before the next value was emitted.
-
3.0.030 Dec 2025Release notes
Open source →What's Changed
-
[Breaking]
anyBeacon.next()now throws if the beacon is disposed while waiting for the next value. This is a breaking change because previously it would complete with the current value if the beacon was disposed. -
[Feat] Add
anyBeacon.nextOrNull()method that returnsnullif the beacon is disposed while waiting for the next value.
Full Changelog: v2.0.3...v3.0.0
Release notes
Open source →-
[Breaking]
anyBeacon.next()now throws if the beacon is disposed while waiting for the next value. This is a breaking change because previously it would complete with the current value if the beacon was disposed. -
[Feat] Add
anyBeacon.nextOrNull()method that returnsnullif the beacon is disposed while waiting for the next value.
-
-
2.0.428 Dec 2025 -
2.0.320 Dec 2025Release notes
Open source →What's Changed
- fix- dirty status calculation in derived which behaved wrong when the value is nullable by @JinyuS in #164
- V2.0.3-release by @JinyuS in #165
Full Changelog: v2.0.2...v2.0.3
Release notes
Open source →-[Fix] Nullable derived beacons didn't send notifications in some instances.
-
2.0.219 Dec 2025Release notes
Open source →What's Changed
- Create special class for subscriptions on derived beacons by @JinyuS in #159
- V2.0.1-release by @JinyuS in #160
- Add BeaconGroup.textEditing by @JinyuS in #161
- add select extension methods to beaconcontroller by @JinyuS in #162
- V2.0.2-release by @JinyuS in #163
Full Changelog: v2.0.0...v2.0.2
Release notes
Open source →- [Feature] Add
select,select2andselect3methods to BeaconController which makes it easier to watch 1-3 beacons from a Controller.
final (age, name) = myController.select2(context, (c) => (c.ageBeacon, c.nameBeacon));- [Feature] add BeaconGroup.textEditing() as a more convenient way of creating a TextEditingBeacon that's tied to a group.
old:
final usernameField = TextEditingBeacon(text:'', group:B)new:
final usernameField = B.textEditing(text:'') -
2.0.118 Dec 2025 -
2.0.017 Dec 2025Release notes
Open source →What's Changed
Breaking Changes
-
Remove synchronous subscriptions on DerivedBeacon: Only available for Writable and BufferedBeacons.
-
Chaining methods are now asynchronous: ie: map, filter, debounce, throttle, buffer, and bufferTime now operate asynchronously
-
Immutable chained beacons: The beacons returned from chaining methods are now immutable.
-
Stream access change: anyBeacon.toStream() is now anyBeacon.stream
-
Filter allowFirst parameter: The lazyBypass parameter in FilteredBeacon was replaced with allowFirst (set to false by default)
-
Debounce allowFirst parameter: Added allowFirst parameter to lazyDebounced and debounce chain method (set to false by default)
Full Changelog: https://github.com/jinyus/dart_beacon/blob/647fb0bdb664533fdefdfae106255652c6ad18b9/packages/state_beacon/CHANGELOG.md
Release notes
Open source →-
[Breaking]
anyBeacon.toStream()is nowanyBeacon.stream -
[Breaking] The lazyBypass parameter in
.filter()chain method was replaced with allowFirst (set to false by default).Previously, the first value sent to a lazy filtered beacon would not be filtered as
lazyBypasswastrueby default. This caused confusion as most persons expect it to be filtered. The name of the parameter has been changed toallowFirstand it is set tofalseby default.OLD
final count = Beacon.writable(0); final gtThan10 = count.filter((prev,next) => next>10); expect(gtThan10.peek(), 0); // first value was set immediatelyNEW
final count = Beacon.writable(0); final gtThan10 = count.filter((prev,next) => next>10); expect(gtThan10.peek, throwsException) // no value has been set as yet count.value = 20; await gtThan10.next(); expect(d.peek(), 20) // value set after passing the filter -
[Breaking] Added allowFirst parameter to lazyDebounced and
.debounce()chain method (set to false by default)Previously, the first value sent to a lazy debounced beacon would not be debounced. It is now debounced by default and you can allow the first value to go through by setting
allowFirsttotrue.OLD
final ms500 = Duration(milliseconds:500); final count = Beacon.writable(0); final d = count.debounce(ms500); expect(d.peek(), 0); // first value was set immediatelyNEW
final ms500 = Duration(milliseconds:500); final count = Beacon.writable(0); final d = count.debounce(ms500); expect(d.peek, throwsException) // no value has been set as yet await Future.delayed(ms500*2); expect(d.peek(), 0) // value set after being debounced -
[Breaking] synchronous parameter has been removed from the
.subscribe()method. Synchronous subscriptions are only available forWritableandBufferedbeacons through the.subscribeSynchronously()method. -
[Breaking] Chaining methods are now asynchronous and return immutable beacons. ie:
map,filter,debounce,throttle,buffer, andbufferTime.These being writable complicated the codebase as writes had to be rerouted to the first mutable beacon in the chain. The alternative is to mutate the original beacon directly.
-
-
1.3.413 Dec 2025Release notes
Open source →- [Fix] synchronous subscription RangeError when disposed in it's callback.
-
1.3.311 Dec 2025Release notes
Open source →What's Changed
- Deprecate supportConditional parameter in effect methods by @JinyuS in #146
- persist forced sets for throttled beacon by @JinyuS in #147
- fix: update remove method to notify only on successful removal by @JinyuS in #148
- fix: update remove method to notify only on successful removal by @JinyuS in #149
- Fix previousValue assignment logic and update tests by @JinyuS in #150
- Prevent immediate callback invocation for subscriptions with startNow=false by @JinyuS in #151
Full Changelog: v1.3.2...v1.3.3
Release notes
Open source →- [Deprecate] deprecate supportConditional parameter in effect methods. This param was already ignored in v0.34.0 but wasn't marked as deprecated
- [Fix] forced writes to throttled beacons incorrectly dropped the
forceflag when those writes were added to the buffer. - [Fix] Map.remove,List.remove and Set.remove no longer notifies listerners when nothing was removed.
- [Fix] previousValue was incorrectly set when using lazy beacons
- [Fix] Edge case where a subscription to a derived beacon with startNow=false would run immediately
-
1.3.206 Dec 2025Release notes
Open source →What's Changed
- Fix method chaining for derived sources by @JinyuS in #142
- V1.3.1-release by @JinyuS in #143
- Make sure dispose is only called once by @JinyuS in #145
Full Changelog: v1.3.0...v1.3.2
-
1.3.104 Dec 2025Release notes
Open source →- [Fix] Chaining methods on derived beacons now eagerly fetches the value allowing it to be used instantly.
final count = Beacon.writable<int>(0); final throttled = Beacon.derived(() => count.value * 2).throttle(k10ms); expect(throttled.value, 0); -
1.3.003 Dec 2025Release notes
Open source →- [Feat] Add queuing to FutureBeacon.updateWith()
The
updateWithmethod calls are now queued when there is an ongoing update. This ensures that all calls are executed in the order they were made, preventing race conditions and inconsistent state.
- [Feat] Add queuing to FutureBeacon.updateWith()
The
-
1.2.002 Dec 2025Release notes
Open source →- [Feat] Add
Future.updateWith()
The
updateWithmethod allows you to update a FutureBeacon's value with the provided callback. This differs fromoverrideWithbecause it updates the value only once, whileoverrideWithreplaces the original callback supplied to the beacon.Future<List<Todo>> loadTodos() async { ... } Future<List<Todo>> addTodo(Todo newTodo) async { await todoService.addTodo(newTodo); final currentTodos = todosBeacon.lastData ?? []; return [newTodo, ...currentTodos]; } final todosBeacon = Beacon.future(() => loadTodos()); // Later, add a new todo without refetching all todos await todosBeacon.updateWith(() => addTodo(newTodo)); // You can also provide an optimistic result // which will be set immediately while the future is being resolved. final optimisticTodos = [newTodo, ...todosBeacon.lastData ?? []]; await todosBeacon.updateWith( () => addTodo(newTodo), optimisticResult: optimisticTodos, ); - [Feat] Add
-
1.1.030 Nov 2025Release notes
Open source →- [Feat] Derived Beacons can now access their own value with '.peek()'. The beacon must have a value so a base case is required.
final counter = Beacon.writable(0); late final ReadableBeacon<int> accumulated; accumulated = Beacon.derived(() { final count = counter.value; if (count == 0) { return 0; // base case } return accumulated.peek() + counter.value; }); -
1.0.229 Nov 2025Release notes
Open source →- [Fix] Bug that caused some widgets to not rebuild when using go_router et al.
- [Refactor] Minor performance improvements.
-
1.0.110 Nov 2025Release notes
Open source →- Bug Fix: Flutter edge-case for derivedBeacons. This was fixed before but the current fix is more efficient.
-
1.0.030 May 2024Release notes
Open source →- [Breaking] Extracted the flutter specific code into a separate package
state_beacon_flutter
- [Breaking] Extracted the flutter specific code into a separate package