UNPKG

mobx

Version:

Simple, scalable state management.

96 lines (95 loc) 3.82 kB
import { CaughtException, IDerivation, IDerivationState, IEqualsComparer, IObservable, IValueDidChange, Lambda, TraceMode } from "../internal"; export interface IComputedValue<T> { get(): T; set(value: T): void; observe(listener: (change: IValueDidChange<T>) => void, fireImmediately?: boolean): Lambda; } export interface IComputedValueOptions<T> { get?: () => T; set?: (value: T) => void; name?: string; equals?: IEqualsComparer<T>; context?: any; requiresReaction?: boolean; keepAlive?: boolean; } /** * A node in the state dependency root that observes other nodes, and can be observed itself. * * ComputedValue will remember the result of the computation for the duration of the batch, or * while being observed. * * During this time it will recompute only when one of its direct dependencies changed, * but only when it is being accessed with `ComputedValue.get()`. * * Implementation description: * 1. First time it's being accessed it will compute and remember result * give back remembered result until 2. happens * 2. First time any deep dependency change, propagate POSSIBLY_STALE to all observers, wait for 3. * 3. When it's being accessed, recompute if any shallow dependency changed. * if result changed: propagate STALE to all observers, that were POSSIBLY_STALE from the last step. * go to step 2. either way * * If at any point it's outside batch and it isn't observed: reset everything and go to 1. */ export declare class ComputedValue<T> implements IObservable, IComputedValue<T>, IDerivation { dependenciesState: IDerivationState; observing: IObservable[]; newObserving: null; isBeingObserved: boolean; isPendingUnobservation: boolean; observers: Set<any>; diffValue: number; runId: number; lastAccessedBy: number; lowestObserverState: IDerivationState; unboundDepsCount: number; __mapid: string; protected value: T | undefined | CaughtException; name: string; triggeredBy?: string; isComputing: boolean; isRunningSetter: boolean; derivation: () => T; setter?: (value: T) => void; isTracing: TraceMode; scope: Object | undefined; private equals; private requiresReaction; private keepAlive; /** * Create a new computed value based on a function expression. * * The `name` property is for debug purposes only. * * The `equals` property specifies the comparer function to use to determine if a newly produced * value differs from the previous value. Two comparers are provided in the library; `defaultComparer` * compares based on identity comparison (===), and `structualComparer` deeply compares the structure. * Structural comparison can be convenient if you always produce a new aggregated object and * don't want to notify observers if it is structurally the same. * This is useful for working with vectors, mouse coordinates etc. */ constructor(options: IComputedValueOptions<T>); onBecomeStale(): void; onBecomeObservedListeners: Set<Lambda> | undefined; onBecomeUnobservedListeners: Set<Lambda> | undefined; onBecomeObserved(): void; onBecomeUnobserved(): void; /** * Returns the current value of this computed value. * Will evaluate its computation first if needed. */ get(): T; peek(): T; set(value: T): void; private trackAndCompute; computeValue(track: boolean): T | CaughtException; suspend(): void; observe(listener: (change: IValueDidChange<T>) => void, fireImmediately?: boolean): Lambda; warnAboutUntrackedRead(): void; toJSON(): T; toString(): string; valueOf(): T; [Symbol.toPrimitive](): T; } export declare const isComputedValue: (x: any) => x is ComputedValue<{}>;