set method
- T newValue
Sets the value of this node and notifies all active subscribers.
If newValue is equal to the current value (via ==), this is a
no-op: the value is unchanged and no subscribers are notified.
That includes AsyncData / AsyncLoading / AsyncError when their
payloads compare equal (for example AsyncData(sameUser) twice).
Do not re-set an equal value to kick side effects (resume a deferred scope, re-run sync, refresh listeners). Use invalidate to force a notification without changing the value, or model the signal on a dedicated node / callback instead of piggybacking on identity state.
If the node has been disposed, the call is silently ignored (a concise debug message is printed in debug mode). This soft-fail behavior prevents crashes from late async writes that land after scope disposal.
Implementation
void set(T newValue) {
if (_isDisposed) {
// Late async writes after disposal are common and usually harmless (the
// UI/scope is simply gone). Fail softly instead of throwing so callers
// don't need to manually guard every post-await mutation.
assert(() {
Zenith.onDebugPrint?.call(
'ZenithNode<$T>.set() ignored: node is disposed',
);
return true;
}());
return;
}
T effectiveValue = newValue;
for (final mw in _middleware) {
final intercepted = mw.onWillSet(this, _value, effectiveValue);
if (intercepted == null) {
return; // Write canceled by middleware
}
effectiveValue = intercepted;
}
if (_value == effectiveValue) {
return;
}
final oldValue = _value;
if (oldValue is Zeroizable && !identical(oldValue, effectiveValue)) {
oldValue.zeroize();
}
_value = effectiveValue;
Zenith.observer?.onNodeMutated(this, oldValue, effectiveValue);
notifySubscribers();
for (final mw in _middleware) {
mw.onDidSet(this, effectiveValue);
}
}