Maintaining a Store
Look at code to maintain a store in this lesson.
We'll cover the following...
One problem with a reducer on its own is the possibility that different callers to the reducer might get out of sync. A solution to that is to also maintain a store. For our purposes here, a store is a centralized object that manages access to both a single source of central data and a related reducer. For our coin example, a store might look like this:
export class CoinStore {
static state = {count: 0, value: 0}
static getState(): { return state }
static dispatch(action) {
CoinStore.state = reducer(CoinStore.state, action)
return CoinStore.state
}
}
Again, we’re holding off on TypeScript annotations. This code sets up a store with a single point of access:
CoinStore.dispatch({type: "AddPenny"})
CoinStore.dispatch({type: "AddNickel"})
const finalState = CoinStore.getState()
In this case, you know that your return value from dispatch
is the current state, but typically you only ask for the state explicitly, otherwise, you act on it only through actions.
Okay, what does that look like in our actual store, and how can we use TypeScript to help us make sure we get all the details right?
The store in TypeScript
Here’s what our store looks like in TypeScript:
export interface CalendarFilterSubscriber {calendarFilterChanged(store: CalendarFilterStore): void}interface CalendarFilterState {filterStates: { [key: string]: boolean }}interface AddFilterAction {type: "AddFilter"dateString: string}interface ToggleDateAction {type: "ToggleDate"dateString: string}interface ClearAllAction {type: "ClearAll"}type Action = AddFilterAction | ToggleDateAction | ClearAllActionexport var initialState = { filterStates: {} }export class CalendarFilterStore {static state: CalendarFilterState = initialStatestatic subscribers: CalendarFilterSubscriber[] = []static getState(): CalendarFilterState {return CalendarFilterStore.state}static dispatch(action: Action): CalendarFilterState {CalendarFilterStore.state = CalendarFilterStore.reducer(CalendarFilterStore.state,action)CalendarFilterStore.update()return CalendarFilterStore.state}static update() {CalendarFilterStore.subscribers.forEach(subscriber =>subscriber.calendarFilterChanged(CalendarFilterStore.state))}static subscribe(subscriber: CalendarFilterSubscriber): void {CalendarFilterStore.subscribers.push(subscriber)}static reducer(state: CalendarFilterState,action: Action): CalendarFilterState {switch (action.type) {case "AddFilter": {const filterStates = {...state.filterStates,[action.dateString]: false,}return { ...state, filterStates: filterStates }}case "ToggleDate": {if (!(action.dateString in state.filterStates)) {return { ...state }}const filterStates = {...state.filterStates,[action.dateString]: !state.filterStates[action.dateString],}return {...state,filterStates: filterStates,}}case "ClearAll": {const newState = initialStatefor (const date in state.filterStates) {newState.filterStates[date] = false}return newState}}}}
Explanation
Quite a bit to get through here. The first ...