value property

T get value

Gets the current computed value.

If read within a reactive context (like an Effect or another Computed), it automatically registers itself as a dependency of that context.

Recalculates the value only if it is marked dirty. If evaluation is already in progress on the call stack, throws a StateError to prevent circular dependencies.

Implementation

T get value {
  if (_isComputing) {
    throw _CircularComputedDependencyError();
  }

  // 1. Dependency tracking for any active outer consumer (e.g. Effect or outer Computed)
  final active = activeConsumer;
  if (active != null) {
    addObserver(active);
    if (active is DependencyTracker) {
      active.addDependency(this);
    }
  }

  // 2. Recompute and cache if dirty
  if (_isDirty) {
    _isComputing = true;
    pushConsumer(this);
    try {
      clearDependencies();
      _cachedValue = _computeFn();
      _error = null;
      _errorStackTrace = null;
      _isDirty = false;
    } catch (error, stackTrace) {
      if (error is _CircularComputedDependencyError) {
        // A circular evaluation must not leave computeds observing each
        // other forever.
        clearDependencies();
      } else {
        // Cache failures just like values. A dependency change marks this
        // computed dirty and lets observing effects recover automatically.
        _error = error;
        _errorStackTrace = stackTrace;
        _isDirty = false;
      }
      rethrow;
    } finally {
      popConsumer();
      _isComputing = false;
    }
  }

  final error = _error;
  if (error != null) {
    Error.throwWithStackTrace(error, _errorStackTrace!);
  }

  return _cachedValue as T;
}