Skip to content

History

History is Synapse's abstraction over a stack of navigation states; Router delegates all state bookkeeping to it, and App exposes it as the history property. BrowserHistory is the implementation that syncs with the real browser address bar and window.history.

History

An in-memory stack, used by default (an App/Router created without an explicit history gets a plain new History()).

ts
import { History } from '@chialab/synapse';

const history = new History();
history.start(); // resets internal state and marks it active

Key members:

  • start() / stop() — activate/deactivate the instance; active reflects the current state. start() calls reset(), clearing all entries.
  • pushState(state) / replaceState(state) — record a State ({ url, path, title, data, request, response }, see Request & Response) as a new entry or in place of the current one; both emit a 'pushstate'/'replacestate' event with { state, previous } and return the stored HistoryState.
  • go(shift) / back() / forward() — move the internal index by shift (or ±1) and emit 'popstate' with { state, previous }; out-of-range shifts are ignored.
  • state — the current State, states — the full list, index — the current position, length — the number of entries.
  • compareStates(state1, state2) — returns NavigationDirection.back if state2 sits before state1 in the stack, NavigationDirection.forward otherwise. This is what App#onPopState uses to compute navigationDirection.

History extends the internal Emitter, so you can also do history.on('pushstate' | 'replacestate' | 'popstate', listener) directly.

BrowserHistory

Syncs the same API with window.history and the browser's popstate event, so back/forward buttons and the address bar work as expected.

ts
import { render } from '@chialab/dna';
import { BrowserHistory } from '@chialab/synapse';

const app = render(<DemoApp base="/" history={new BrowserHistory()} />, document.body);
app.start();
  • Only one active BrowserHistory is allowed at a time; calling start() on a second instance while another is active throws You cannot initialize more than one "BrowserHistory"..
  • pushState/replaceState call through to History and then to window.history.pushState/replaceState, serializing the HistoryState (via JSON.parse(JSON.stringify(...))) so it's safe to store natively.
  • go(shift) delegates to window.history.go() and resolves once the corresponding native popstate fires.
  • Native popstate events are translated back into Synapse's 'popstate' event: if the event carries a recognizable HistoryState from this session, the internal index is updated (or the stack is reset, if the state belongs to a different History instance — e.g. after a full reload); otherwise (e.g. a hash-only navigation typed by hand) it's re-resolved from window.location.href.
  • listen() / unlisten() are deprecated aliases for start() / stop().

In a demo-app element, this is set declaratively, as in the demo/navigation example:

ts
import { html, render } from '@chialab/dna';
import { BrowserHistory } from '@chialab/synapse';

const app = render(html`<demo-app base=${`${location.pathname}#!/`} history=${new BrowserHistory()} />`, document.body);
app.start();

compareStates() returns one of the two 'back' / 'forward' string values (internally a NavigationDirection enum). App exposes the result as its navigationDirection state property, reflected in the :navigation attribute of the app element — useful for CSS-driven transition direction (see Page & Transition).

Client-side routing, middlewares and page transitions on top of Web Components.