Share state between pages

One native app can show several bundles, or several pages of one project, and each is its own Angular app. LynxSessionStorage gives them a shared key-value store that lasts as long as the app is running.

It isn't the browser's sessionStorage, which belongs to one tab. Every Lynx view in the host app (the native app that runs your bundles) sees the same keys. The store empties when the app quits.

In the web preview and in tests

The web preview and unit tests have no native store, so LynxSessionStorage keeps values in memory instead. Every method works, but each page gets its own store, so nothing is shared.

Write a value and watch it

src/app/app.ts
import { Component, inject } from '@angular/core';
import { LYNX_ELEMENTS, LynxSessionStorage } from '@blotch/angular-lynx';

@Component({
  selector: 'app-root',
  imports: [LYNX_ELEMENTS],
  template: `
    <view (bindtap)="increment()">
      <text>Count: {{ count() ?? 'not set' }}</text>
    </view>
  `,
})
export class App {
  readonly #sessionStorage = inject(LynxSessionStorage);

  readonly count = this.#sessionStorage.watch<number>('count');

  increment(): void {
    this.#sessionStorage.setItem('count', (this.count() ?? 0) + 1);
  }
}
  • setItem(key, value) stores a value under a key. Store a plain object, or a single value such as a string or a number.
  • watch(key) returns a signal for the key. It starts as undefined, then holds the stored value.
  • Call watch() in a field initializer or constructor. It stops listening when the component is destroyed. Elsewhere, pass an injector: watch('count', { injector }).
  • Call setItem() again after a change. On a device the store keeps a copy, so changing an object after you store it doesn't update what other pages read.

Read a value once

const count = await this.#sessionStorage.getItem<number>('count');

getItem() returns a Promise of the stored value. Handle a key that was never set with ??, as the first example does.

When another page's changes appear

On a phone, the copy of your app that draws the UI runs on the main thread. Lynx doesn't send change notifications there. So a watch() signal:

  • updates right away when the same page calls setItem()
  • picks up other pages' values when the signal is created
  • doesn't update when another page writes the key later

To see a newer value from another page, call getItem() again.

Subscribe with a callback

For code that doesn't use signals, subscribe() calls you back when the key changes:

const subscription = this.#sessionStorage.subscribe<number>('count', (value) =>
  console.log('count is now', value),
);

// When you no longer need it:
this.#sessionStorage.unsubscribe(subscription);

Unsubscribe yourself: unlike watch(), a subscription doesn't end with the component. The same rule about other pages' changes applies.