@s-libs/app-state
    Preparing search index...

    Class PersistentStore<State, Persisted>

    A store that is automatically saved to and restored from local storage. This is suitable for small stores that can very quickly be (de)serialized to/from JSON without any noticeable delay.

    class MyState implements VersionedObject {
    _version = 1;
    // eslint-disable-next-line camelcase -- will fix in next version
    my_state_key = 'my state value';
    }

    class MyStore extends PersistentStore<MyState> {
    constructor() {
    super('myPersistenceKey', new MyState());
    }
    }

    let store = new MyStore();
    store('my_state_key').set('my new value');

    // the user leaves the page and comes back later ...

    store = new MyStore();
    expect(store.state().my_state_key).toBe('my new value');

    At this point, if you change _version the store will be reset to the default state. This is a convenience during initial development of your app. Once it is released to real users, you will want to use a MigrationManager to avoid wiping out your users' data:

    class MyState implements VersionedObject {
    _version = 2; // bump version to 2
    myStateKey = 'my state value'; // schema change: my_state_key => myStateKey
    }

    class MyMigrationManager extends MigrationManager<MyState> {
    constructor() {
    super();
    this.registerMigration(1, this.#migrateFromV1);
    }

    #migrateFromV1(oldState: any): any {
    return { _version: 2, myStateKey: oldState.my_state_key };
    }
    }

    class MyStore extends PersistentStore<MyState> {
    constructor() {
    // pass in our new `MyMigrationManager`
    super('myPersistenceKey', new MyState(), {
    migrator: new MyMigrationManager(),
    });
    }
    }

    // the store gets the value persisted from version 1 in our previous example
    const store = new MyStore();
    expect(store.state().myStateKey).toBe('my new value');

    If you want to persist something a little different from what is in the store, for example to omit some properties, use a PersistenceCodec:

    class MyState implements VersionedObject {
    _version = 1;
    sessionStart = Date.now();
    }
    type Persisted = Omit<MyState, 'sessionStart'>;

    class MyCodec implements PersistenceCodec<MyState, Persisted> {
    encode(left: MyState): Persisted {
    return omit(left, 'sessionStart');
    }

    decode(right: Persisted): MyState {
    return { ...right, sessionStart: Date.now() };
    }
    }

    class MyStore extends PersistentStore<MyState, Persisted> {
    constructor() {
    super('myPersistenceKey', new MyState(), { codec: new MyCodec() });
    }
    }

    const session1Start = Date.now();
    let store = new MyStore();
    expect(store.state().sessionStart).toBe(session1Start);
    expect(localStorage.getItem('myPersistenceKey')).toBe('{"_version":1}');

    // the user leaves the page and comes back later...

    tick(300_000); // 5 minutes pass
    store = new MyStore();
    expect(store.state().sessionStart).toBe(session1Start + 300_000);

    Type Parameters

    • State extends VersionedObject
    • Persisted extends VersionedObject = State

    Hierarchy (View Summary)

    Index

    Constructors

    Properties

    $: Observable<State> = ...

    An Observable of the state of this store object.

    activeChildren: Map<string, Set<Store<unknown>>> = ...
    getRootStore: () => RootStore<object>
    lastKnownState?: State
    subscribers: Map<Subscriber<State>, undefined | State> = ...

    Methods

    • Assigns the given values to state of this store object. The resulting state will be like Object.assign(store.state(), value).

      Parameters

      • value: Partial<T>

      Returns void

    • Turns off this store's observables while func is executing, emitting only once afterward, if the store changed. This allows you to batch multiple mutations into a single update at the end.

      store.batch(() => {
      store.assign({ key1: value1 });
      store('key2').delete();
      store('key3').set({ key4: value4 });

      store('key1').state(); // returns `value1`
      });

      Parameters

      • func: VoidFunction

      Returns void

    • Runs func on a shallow clone of the state, replacing the state with the clone. The first argument to func will be the cloned state, followed by the arguments in args.

      WARNING: You SHOULD NOT use a function that will mutate nested objects within the state.

      Type Parameters

      • A extends any[]

      Parameters

      • func: (state: State, ...args: A) => void
      • ...args: A

      Returns void

    • Runs func on the state and replaces it with the return value. The first argument to func will be the state, followed by the arguments in args.

      WARNING: You SHOULD NOT use a function that will mutate the state.

      Type Parameters

      • A extends any[]

      Parameters

      Returns void