In the previous blog post I took a look at the Observable State Store Pattern and build a simple Observable State Store.

In the past days I extended the code and published it in a public GitHub repository

Some items I have changed over time.

I started to introduce State classes. The idea is to encapsulate all state items of a specifc store in a State class. So for example the TrackStateStore is a store which consists of a list of tracks (songs) and it also manages the selected track of this list. So I decided to introduce a TrackState class:

import { Track } from '../types/track';

export class TrackState {
    tracks: Track[];
    selectedIndex: number;
}

So the new TrackStateStore now extends StateStoreBase<TrackState>

@Injectable({ providedIn: 'root' })
export class TrackStateStore 
  extends StateStoreBase<TrackState> 
  implements TrackStateStoreActions {
    ....
  }

To interact with the store I experimented a bit with Redux but I felt it is way too heavy for this scenario. Redux adds quite some additional complexity so to keep it basic I decided to introduce StoreActions instead. StoreActions is just an interface which defines all interactions with the state store. So for example the TrackStateStore implements the TrackStateStoreActions interface:

export interface TrackStateStoreActions {
    next(): void;
    previous(): void;
    reset(): void;
}

A StoreAction function to select the next track in the TrackStateStore can be implemented on the store like:

 public next(): void {
      const state: TrackState = this._state$.value;
      let index: number = state.selectedIndex+1;
      state.selectedIndex = index < state.tracks.length ? index : 0;
      
      this._state$.next(state);
}

This implementation has a build in “repeat” functionality, this code is easily testable by writing a jasmine spec:

it('next should increase selected index', done => {
    stateStore.next();
    stateStore.next();

    stateStore.value$.subscribe(state => {
      expect(state.selectedIndex).toBe(2);
      done();
    });
  });

I published the code on my GitHub repository all feedback is welcome and please feel free to:

  • Use the code in your projects
  • Fork the repository
  • Contribute by adding issues
  • Contribute by adding Pull Requests